From efcbe5762463186cf0c24c94390a36d16968c428 Mon Sep 17 00:00:00 2001
From: Prayas Mohanty <pmohanty@nvidia.com>
Date: Wed, 27 May 2020 02:10:15 +0530
Subject: [PATCH] argus: add EVENT_TYPE_ERROR to sample apps

Sample apps like userAutoExposure and userAutoWhiteBalance
did not have EVENT_TYPE_ERROR registered to catch error
events from Argus. Register for the event and proceed
to clean-up in case of error.

Bug 2791154
Bug 200617592

Change-Id: I6febaf61c909f322dabba0f619cdc180652221a2
Reviewed-on: https://git-master.nvidia.com/r/c/tegra/camera/argus/+/2350706
(cherry picked from commit ea7000f243d413e07fc996a9d574a6552fcd073e)
Reviewed-on: https://git-master.nvidia.com/r/c/tegra/camera/argus/+/2355233
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Devang Kubavat <dkubavat@nvidia.com>
Reviewed-by: Prayas Mohanty <pmohanty@nvidia.com>
Reviewed-by: Shantanu Nath <snath@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
Tested-by: Prayas Mohanty <pmohanty@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
---
 public/samples/userAutoExposure/main.cpp     | 466 +++++++++++++++------------
 public/samples/userAutoWhiteBalance/main.cpp | 388 ++++++++++++----------
 2 files changed, 475 insertions(+), 379 deletions(-)
 mode change 100644 => 100755 public/samples/userAutoExposure/main.cpp
 mode change 100644 => 100755 public/samples/userAutoWhiteBalance/main.cpp

diff --git a/public/samples/userAutoExposure/main.cpp b/public/samples/userAutoExposure/main.cpp
old mode 100644
new mode 100755
index dede616..b03fbee
--- a/public/samples/userAutoExposure/main.cpp
+++ b/public/samples/userAutoExposure/main.cpp
@@ -88,6 +88,51 @@ protected:
     Value<bool> m_useAverageMap;
 };
 
+/**
+ * RAII class for app teardown
+ */
+class UserAutoExposureTeardown
+{
+public:
+    CameraProvider* m_cameraProvider;
+    PreviewConsumerThread* m_previewConsumerThread;
+    OutputStream* m_stream;
+
+    UserAutoExposureTeardown()
+    {
+        m_cameraProvider = NULL;
+        m_previewConsumerThread = NULL;
+        m_stream = NULL;
+    }
+
+    ~UserAutoExposureTeardown()
+    {
+        shutdown();
+    }
+
+private:
+    void shutdown()
+    {
+        // Destroy the output streams (stops consumer threads).
+        if (m_stream != NULL)
+            m_stream->destroy();
+
+        // Wait for the consumer threads to complete.
+        if (m_previewConsumerThread != NULL)
+            PROPAGATE_ERROR_CONTINUE(m_previewConsumerThread->shutdown());
+
+        // Shut down Argus.
+        if (m_cameraProvider != NULL)
+            m_cameraProvider->destroy();
+
+        // Shut down the window (destroys window's EGLSurface).
+        Window::getInstance().shutdown();
+
+        // Cleanup the EGL display
+        PROPAGATE_ERROR_CONTINUE(g_display.cleanup());
+    }
+};
+
 /*
  * Program: userAutoExposure
  * Function: To display preview images to the device display to illustrate a Bayer
@@ -95,25 +140,24 @@ protected:
  */
 static bool execute(const UserAutoExposureSampleOptions& options)
 {
+    UserAutoExposureTeardown appTearDown;
     // Initialize the window and EGL display.
-    Window &window = Window::getInstance();
-    window.setWindowRect(options.windowRect());
-    PROPAGATE_ERROR(g_display.initialize(window.getEGLNativeDisplay()));
+    Window::getInstance().setWindowRect(options.windowRect());
+    PROPAGATE_ERROR(g_display.initialize(Window::getInstance().getEGLNativeDisplay()));
 
     /*
      * Set up Argus API Framework, identify available camera devices, create
      * a capture session for the first available device, and set up the event
      * queue for completed events
      */
-
-    UniqueObj<CameraProvider> cameraProvider(CameraProvider::create());
-    ICameraProvider *iCameraProvider = interface_cast<ICameraProvider>(cameraProvider);
+    appTearDown.m_cameraProvider = CameraProvider::create();
+    ICameraProvider *iCameraProvider = interface_cast<ICameraProvider>(appTearDown.m_cameraProvider);
     EXIT_IF_NULL(iCameraProvider, "Cannot get core camera provider interface");
     USER_AUTO_EXPOSURE_PRINT("Argus Version: %s\n", iCameraProvider->getVersion().c_str());
 
     // Get the selected camera device and sensor mode.
     CameraDevice* cameraDevice = ArgusHelpers::getCameraDevice(
-            cameraProvider.get(), options.cameraDeviceIndex());
+        appTearDown.m_cameraProvider, options.cameraDeviceIndex());
     if (!cameraDevice)
         ORIGINATE_ERROR("Selected camera device is not available");
     SensorMode* sensorMode = ArgusHelpers::getSensorMode(cameraDevice, options.sensorModeIndex());
@@ -123,7 +167,7 @@ static bool execute(const UserAutoExposureSampleOptions& options)
 
     // Create the CaptureSession using the selected device.
     UniqueObj<CaptureSession> captureSession(iCameraProvider->createCaptureSession(cameraDevice));
-    ICaptureSession *iSession = interface_cast<ICaptureSession>(captureSession);
+    ICaptureSession* iSession = interface_cast<ICaptureSession>(captureSession);
     EXIT_IF_NULL(iSession, "Cannot get Capture Session Interface");
 
     IEventProvider *iEventProvider = interface_cast<IEventProvider>(captureSession);
@@ -131,6 +175,10 @@ static bool execute(const UserAutoExposureSampleOptions& options)
 
     std::vector<EventType> eventTypes;
     eventTypes.push_back(EVENT_TYPE_CAPTURE_COMPLETE);
+    eventTypes.push_back(EVENT_TYPE_ERROR);
+    /* Seems there is bug in Argus, which drops EVENT_TYPE_ERROR if all
+    3 events are not set. Set it for now */
+    eventTypes.push_back(EVENT_TYPE_CAPTURE_STARTED);
     UniqueObj<EventQueue> queue(iEventProvider->createEventQueue(eventTypes));
     IEventQueue *iQueue = interface_cast<IEventQueue>(queue);
     EXIT_IF_NULL(iQueue, "event queue interface is NULL");
@@ -156,14 +204,14 @@ static bool execute(const UserAutoExposureSampleOptions& options)
                                                        options.windowRect().height()));
     iEGLStreamSettings->setEGLDisplay(g_display.get());
 
-    UniqueObj<OutputStream> stream(iSession->createOutputStream(streamSettings.get()));
-    IEGLOutputStream *iEGLOutputStream = interface_cast<IEGLOutputStream>(stream);
+    appTearDown.m_stream = iSession->createOutputStream(streamSettings.get());
+    IEGLOutputStream *iEGLOutputStream = interface_cast<IEGLOutputStream>(appTearDown.m_stream);
     EXIT_IF_NULL(iEGLOutputStream, "Cannot get IEGLOutputStream Interface");
 
-    PreviewConsumerThread previewConsumerThread(
+    appTearDown.m_previewConsumerThread = new PreviewConsumerThread(
         iEGLOutputStream->getEGLDisplay(), iEGLOutputStream->getEGLStream());
-    PROPAGATE_ERROR(previewConsumerThread.initialize());
-    PROPAGATE_ERROR(previewConsumerThread.waitRunning());
+    PROPAGATE_ERROR(appTearDown.m_previewConsumerThread->initialize());
+    PROPAGATE_ERROR(appTearDown.m_previewConsumerThread->waitRunning());
 
     UniqueObj<Request> request(iSession->createRequest(CAPTURE_INTENT_MANUAL));
     IRequest *iRequest = interface_cast<IRequest>(request);
@@ -191,7 +239,7 @@ static bool execute(const UserAutoExposureSampleOptions& options)
     EXIT_IF_NOT_OK(iSourceSettings->setSensorMode(sensorMode),
         "Unable to set the SensorMode in the Request");
 
-    EXIT_IF_NOT_OK(iRequest->enableOutputStream(stream.get()),
+    EXIT_IF_NOT_OK(iRequest->enableOutputStream(appTearDown.m_stream),
         "Failed to enable stream in capture request");
 
     // Start off the min exposure time.
@@ -227,222 +275,222 @@ static bool execute(const UserAutoExposureSampleOptions& options)
     for (uint32_t frameCaptureLoop = 0; frameCaptureLoop < options.frameCount(); frameCaptureLoop++)
     {
         // Keep PREVIEW display window serviced
-        window.pollEvents();
+        Window::getInstance().pollEvents();
 
-        const uint64_t ONE_SECOND = 1000000000;
-        iEventProvider->waitForEvents(queue.get(), ONE_SECOND);
+        const uint64_t FIVE_SECONDS = 5000000000;
+        iEventProvider->waitForEvents(queue.get(), FIVE_SECONDS);
         EXIT_IF_TRUE(iQueue->getSize() == 0, "No events in queue");
 
         const Event* event = iQueue->getEvent(iQueue->getSize() - 1);
-        const IEventCaptureComplete *iEventCaptureComplete
-            = interface_cast<const IEventCaptureComplete>(event);
-        EXIT_IF_NULL(iEventCaptureComplete, "Failed to get EventCaptureComplete Interface");
-
-        const CaptureMetadata *metaData = iEventCaptureComplete->getMetadata();
-        const ICaptureMetadata* iMetadata = interface_cast<const ICaptureMetadata>(metaData);
-        EXIT_IF_NULL(iMetadata, "Failed to get CaptureMetadata Interface");
-
-        uint64_t frameExposureTime = iMetadata->getSensorExposureTime();
-        float frameGain = iMetadata->getSensorAnalogGain();
-
-        USER_AUTO_EXPOSURE_PRINT("Frame metadata ExposureTime %ju, Analog Gain %f\n",
-            frameExposureTime, frameGain);
-
-        float curExposureLevel;
-
-        if (!options.useAverageMap())
-        {
-            /*
-             * By using the Bayer Histogram, find the exposure middle point
-             * in the histogram to be used as a guide as to whether to increase
-             * or decrease the Exposure Time or Analog Gain
-             */
-
-            const IBayerHistogram* bayerHistogram =
-                interface_cast<const IBayerHistogram>(iMetadata->getBayerHistogram());
-            EXIT_IF_NULL(bayerHistogram, "Unable to get Bayer Histogram from metadata");
-
-            std::vector< BayerTuple<uint32_t> > histogram;
-            EXIT_IF_NOT_OK(bayerHistogram->getHistogram(&histogram), "Failed to get histogram");
-
-            uint64_t halfPixelTotal = (uint64_t)sensorModeResolution.area() *
-                                      BAYER_CHANNEL_COUNT / 2;
-            uint64_t sum = 0;
-            uint64_t currentBin;
-            for (currentBin = 0; currentBin < histogram.size(); currentBin++)
-            {
-                sum += histogram[currentBin].r()
-                    +  histogram[currentBin].gEven()
-                    +  histogram[currentBin].gOdd()
-                    +  histogram[currentBin].b();
-                if (sum > halfPixelTotal)
-                {
-                    break;
-                }
-            }
-            curExposureLevel = (float) ++currentBin / (float)histogram.size();
-        }
-        else
-        {
-            /*
-             * By using the Bayer Average Map, find the average point in the
-             * region to be used as a guide as to whether to increase or
-             * decrease the Exposure Time or Analog Gain
-             */
-
-            const Ext::IBayerAverageMap* iBayerAverageMap =
-                interface_cast<const Ext::IBayerAverageMap>(metaData);
-            EXIT_IF_NULL(iBayerAverageMap, "Failed to get IBayerAverageMap interface");
-            Array2D< BayerTuple<float> > averages;
-            EXIT_IF_NOT_OK(iBayerAverageMap->getAverages(&averages),
-                "Failed to get averages");
-            Array2D< BayerTuple<uint32_t> > clipCounts;
-            EXIT_IF_NOT_OK(iBayerAverageMap->getClipCounts(&clipCounts),
-                "Failed to get clip counts");
-            uint32_t pixelsPerBinPerChannel = iBayerAverageMap->getBinSize().width() *
-                                              iBayerAverageMap->getBinSize().height() /
-                                              BAYER_CHANNEL_COUNT;
-            float centerX = (float)(averages.size().width()-1) / 2;
-            float centerY = (float)(averages.size().height()-1) / 2;
-
-            // Using the BayerAverageMap, get the average instensity across the checked area
-            float weightedPixelCount = 0.0f;
-            float weightedAverageTotal = 0.0f;
-            for (uint32_t x = 0; x < averages.size().width(); x++)
-            {
-                for (uint32_t y = 0; y < averages.size().height(); y++)
+        const IEvent* iEvent = interface_cast<const IEvent>(event);
+        if (!iEvent)
+            printf("Error : Failed to get IEvent interface\n");
+        else {
+            if (iEvent->getEventType() == EVENT_TYPE_CAPTURE_COMPLETE) {
+                const IEventCaptureComplete* iEventCaptureComplete
+                    = interface_cast<const IEventCaptureComplete>(event);
+                EXIT_IF_NULL(iEventCaptureComplete, "Failed to get EventCaptureComplete Interface");
+
+                const CaptureMetadata* metaData = iEventCaptureComplete->getMetadata();
+                const ICaptureMetadata* iMetadata = interface_cast<const ICaptureMetadata>(metaData);
+                EXIT_IF_NULL(iMetadata, "Failed to get CaptureMetadata Interface");
+
+                uint64_t frameExposureTime = iMetadata->getSensorExposureTime();
+                float frameGain = iMetadata->getSensorAnalogGain();
+
+                USER_AUTO_EXPOSURE_PRINT("Frame metadata ExposureTime %ju, Analog Gain %f\n",
+                    frameExposureTime, frameGain);
+
+                float curExposureLevel;
+
+                if (!options.useAverageMap())
                 {
                     /*
-                     * Bin averages disregard pixels which are the result
-                     * of intensity clipping.  A total of these over exposed
-                     * pixels is kept and retrieved by clipCounts(x,y).  The
-                     * following formula treats these pixels as a max intensity
-                     * of 1.0f and adjusts the overall average upwards depending
-                     * on the number of them.
-                     *
-                     * Also, only the GREEN EVEN channel is used to determine
-                     * the exposure level, as GREEN is usually used for luminance
-                     * evaluation, and the two GREEN channels tend to be equivalent
+                     * By using the Bayer Histogram, find the exposure middle point
+                     * in the histogram to be used as a guide as to whether to increase
+                     * or decrease the Exposure Time or Analog Gain
                      */
 
-                    float clipAdjustedAverage =
-                        (averages(x, y).gEven() *
-                            (pixelsPerBinPerChannel - clipCounts(x, y).gEven()) +
-                        clipCounts(x, y).gEven()) / pixelsPerBinPerChannel;
+                    const IBayerHistogram* bayerHistogram =
+                        interface_cast<const IBayerHistogram>(iMetadata->getBayerHistogram());
+                    EXIT_IF_NULL(bayerHistogram, "Unable to get Bayer Histogram from metadata");
 
-                    /*
-                     * This will add the flat averages across the entire image
-                     */
-                    weightedAverageTotal += clipAdjustedAverage;
-                    weightedPixelCount += 1.0f;
+                    std::vector< BayerTuple<uint32_t> > histogram;
+                    EXIT_IF_NOT_OK(bayerHistogram->getHistogram(&histogram), "Failed to get histogram");
 
+                    uint64_t halfPixelTotal = (uint64_t)sensorModeResolution.area() *
+                                                BAYER_CHANNEL_COUNT / 2;
+                    uint64_t sum = 0;
+                    uint64_t currentBin;
+                    for (currentBin = 0; currentBin < histogram.size(); currentBin++)
+                    {
+                        sum += histogram[currentBin].r()
+                            + histogram[currentBin].gEven()
+                            + histogram[currentBin].gOdd()
+                            + histogram[currentBin].b();
+                        if (sum > halfPixelTotal)
+                        {
+                            break;
+                        }
+                    }
+                    curExposureLevel = (float) ++currentBin / (float)histogram.size();
+                }
+                else
+                {
                     /*
-                     * This will add more 'weight' or significance to averages closer to
-                     * the center of the image
+                     * By using the Bayer Average Map, find the average point in the
+                     * region to be used as a guide as to whether to increase or
+                     * decrease the Exposure Time or Analog Gain
                      */
-                    float distance = sqrt((pow(fabs((float)x-centerX),2)) +
-                                          (pow(fabs((float)y-centerY),2)));
-                    if (distance < CENTER_WEIGHTED_DISTANCE)
+
+                    const Ext::IBayerAverageMap* iBayerAverageMap =
+                        interface_cast<const Ext::IBayerAverageMap>(metaData);
+                    EXIT_IF_NULL(iBayerAverageMap, "Failed to get IBayerAverageMap interface");
+                    Array2D< BayerTuple<float> > averages;
+                    EXIT_IF_NOT_OK(iBayerAverageMap->getAverages(&averages),
+                        "Failed to get averages");
+                    Array2D< BayerTuple<uint32_t> > clipCounts;
+                    EXIT_IF_NOT_OK(iBayerAverageMap->getClipCounts(&clipCounts),
+                        "Failed to get clip counts");
+                    uint32_t pixelsPerBinPerChannel = iBayerAverageMap->getBinSize().width() *
+                                                        iBayerAverageMap->getBinSize().height() /
+                                                        BAYER_CHANNEL_COUNT;
+                    float centerX = (float)(averages.size().width() - 1) / 2;
+                    float centerY = (float)(averages.size().height() - 1) / 2;
+
+                    // Using the BayerAverageMap, get the average instensity across the checked area
+                    float weightedPixelCount = 0.0f;
+                    float weightedAverageTotal = 0.0f;
+                    for (uint32_t x = 0; x < averages.size().width(); x++)
+                    {
+                        for (uint32_t y = 0; y < averages.size().height(); y++)
+                        {
+                            /*
+                             * Bin averages disregard pixels which are the result
+                             * of intensity clipping.  A total of these over exposed
+                             * pixels is kept and retrieved by clipCounts(x,y).  The
+                             * following formula treats these pixels as a max intensity
+                             * of 1.0f and adjusts the overall average upwards depending
+                             * on the number of them.
+                             *
+                             * Also, only the GREEN EVEN channel is used to determine
+                             * the exposure level, as GREEN is usually used for luminance
+                             * evaluation, and the two GREEN channels tend to be equivalent
+                             */
+
+                            float clipAdjustedAverage =
+                                (averages(x, y).gEven() *
+                                    (pixelsPerBinPerChannel - clipCounts(x, y).gEven()) +
+                                clipCounts(x, y).gEven()) / pixelsPerBinPerChannel;
+
+                            /*
+                             * This will add the flat averages across the entire image
+                             */
+                            weightedAverageTotal += clipAdjustedAverage;
+                            weightedPixelCount += 1.0f;
+
+                            /*
+                             * This will add more 'weight' or significance to averages closer to
+                             * the center of the image
+                             */
+                            float distance = sqrt((pow(fabs((float)x - centerX), 2)) +
+                                                (pow(fabs((float)y - centerY), 2)));
+                            if (distance < CENTER_WEIGHTED_DISTANCE)
+                            {
+                                weightedAverageTotal += clipAdjustedAverage *
+                                    (1.0f - pow(distance / CENTER_WEIGHTED_DISTANCE, 2)) * CENTER_WEIGHT;
+                                weightedPixelCount +=
+                                    (1.0f - pow(distance / CENTER_WEIGHTED_DISTANCE, 2)) * CENTER_WEIGHT;
+                            }
+                        }
+                    }
+                    if (weightedPixelCount)
+                    {
+                        curExposureLevel = weightedAverageTotal / weightedPixelCount;
+                    }
+                    else
                     {
-                        weightedAverageTotal += clipAdjustedAverage *
-                            (1.0f - pow(distance/CENTER_WEIGHTED_DISTANCE, 2)) * CENTER_WEIGHT;
-                        weightedPixelCount +=
-                            (1.0f - pow(distance/CENTER_WEIGHTED_DISTANCE, 2)) * CENTER_WEIGHT;
+                        curExposureLevel = 1.0f;
                     }
                 }
-            }
-            if (weightedPixelCount)
-            {
-                curExposureLevel = weightedAverageTotal / weightedPixelCount;
-            }
-            else
-            {
-                curExposureLevel = 1.0f;
-            }
-        }
 
-        /*
-         * If the acquired target is outside the target range, then
-         * calculate adjustment values for the Exposure Time and/or the Analog Gain to bring
-         * the next target into range.
-         */
-
-        USER_AUTO_EXPOSURE_PRINT("Exposure level at %0.3f, ", curExposureLevel);
-        if (curExposureLevel > targetRange.max())
-        {
-            if (frameGain > sensorModeAnalogGainRange.min() &&
-                frameExposureTime <= limitExposureTimeRange.min())
-            {
-                frameGain = std::max(frameGain *
-                     TARGET_EXPOSURE_LEVEL / curExposureLevel,
-                     sensorModeAnalogGainRange.min());
-                printf("decreasing analog gain to %f\n", frameGain);
-                EXIT_IF_NOT_OK(iSourceSettings->setGainRange(Range<float>(frameGain)),
-                    "Unable to set the Source Settings Gain Range");
-            }
-            else
-            {
-                frameExposureTime = std::max(limitExposureTimeRange.min(),
-                    (uint64_t) ((float)frameExposureTime *
-                        TARGET_EXPOSURE_LEVEL / curExposureLevel));
-                printf("decreasing Exposure Time to %ju\n", frameExposureTime);
-                EXIT_IF_NOT_OK(iSourceSettings->setExposureTimeRange(
-                    Range<uint64_t>(frameExposureTime)),
-                    "Unable to set the Source Settings Exposure Time Range");
-            }
-        }
-        else if (curExposureLevel < targetRange.min())
-        {
-            if (frameGain < sensorModeAnalogGainRange.max())
-            {
-                frameGain = std::min(frameGain *
-                    TARGET_EXPOSURE_LEVEL / curExposureLevel,
-                    sensorModeAnalogGainRange.max());
-                printf("increasing analog gain to %f\n", frameGain);
-                EXIT_IF_NOT_OK(iSourceSettings->setGainRange(Range<float>(frameGain)),
-                    "Unable to set the Source Settings Gain Range");
+                /*
+                 * If the acquired target is outside the target range, then
+                 * calculate adjustment values for the Exposure Time and/or the Analog Gain to bring
+                 * the next target into range.
+                 */
+
+                USER_AUTO_EXPOSURE_PRINT("Exposure level at %0.3f, ", curExposureLevel);
+                if (curExposureLevel > targetRange.max())
+                {
+                    if (frameGain > sensorModeAnalogGainRange.min() &&
+                        frameExposureTime <= limitExposureTimeRange.min())
+                    {
+                        frameGain = std::max(frameGain *
+                            TARGET_EXPOSURE_LEVEL / curExposureLevel,
+                            sensorModeAnalogGainRange.min());
+                        printf("decreasing analog gain to %f\n", frameGain);
+                        EXIT_IF_NOT_OK(iSourceSettings->setGainRange(Range<float>(frameGain)),
+                            "Unable to set the Source Settings Gain Range");
+                    }
+                    else
+                    {
+                        frameExposureTime = std::max(limitExposureTimeRange.min(),
+                            (uint64_t)((float)frameExposureTime *
+                                TARGET_EXPOSURE_LEVEL / curExposureLevel));
+                        printf("decreasing Exposure Time to %ju\n", frameExposureTime);
+                        EXIT_IF_NOT_OK(iSourceSettings->setExposureTimeRange(
+                            Range<uint64_t>(frameExposureTime)),
+                            "Unable to set the Source Settings Exposure Time Range");
+                    }
+                }
+                else if (curExposureLevel < targetRange.min())
+                {
+                    if (frameGain < sensorModeAnalogGainRange.max())
+                    {
+                        frameGain = std::min(frameGain *
+                            TARGET_EXPOSURE_LEVEL / curExposureLevel,
+                            sensorModeAnalogGainRange.max());
+                        printf("increasing analog gain to %f\n", frameGain);
+                        EXIT_IF_NOT_OK(iSourceSettings->setGainRange(Range<float>(frameGain)),
+                            "Unable to set the Source Settings Gain Range");
+                    }
+                    else
+                    {
+                        frameExposureTime = std::min(limitExposureTimeRange.max(),
+                            (uint64_t)((float)frameExposureTime *
+                                TARGET_EXPOSURE_LEVEL / curExposureLevel));
+                        printf("increasing Exposure Time to %ju\n", frameExposureTime);
+                        EXIT_IF_NOT_OK(iSourceSettings->setExposureTimeRange(
+                            Range<uint64_t>(frameExposureTime)),
+                            "Unable to set the Source Settings Exposure Time Range");
+                    }
+                }
+                else
+                {
+                    printf("currently within target range\n");
+                    continue;
+                }
+                /*
+                 * The modified request is re-submitted to terminate the previous repeat() with
+                 * the old settings and begin captures with the new settings
+                 */
+                iSession->repeat(request.get());
+            } else if (iEvent->getEventType() == EVENT_TYPE_CAPTURE_STARTED) {
+                /* ToDo: Remove the empty after the bug is fixed */
+                continue;
+            } else if (iEvent->getEventType() == EVENT_TYPE_ERROR) {
+                const IEventError* iEventError =
+                    interface_cast<const IEventError>(event);
+                EXIT_IF_NOT_OK(iEventError->getStatus(), "ERROR event");
             }
-            else
-            {
-                frameExposureTime = std::min(limitExposureTimeRange.max(),
-                    (uint64_t) ((float)frameExposureTime *
-                        TARGET_EXPOSURE_LEVEL / curExposureLevel));
-                printf("increasing Exposure Time to %ju\n", frameExposureTime);
-                EXIT_IF_NOT_OK(iSourceSettings->setExposureTimeRange(
-                    Range<uint64_t>(frameExposureTime)),
-                    "Unable to set the Source Settings Exposure Time Range");
+            else {
+                printf("WARNING: Unknown event. Continue\n");
             }
         }
-        else
-        {
-            printf("currently within target range\n");
-            continue;
-        }
-        /*
-         * The modified request is re-submitted to terminate the previous repeat() with
-         * the old settings and begin captures with the new settings
-         */
-        iSession->repeat(request.get());
     }
 
-    iSession->stopRepeat();
-    iSession->waitForIdle();
-
-    // Destroy the output streams (stops consumer threads).
-    stream.reset();
-
-    // Wait for the consumer threads to complete.
-    PROPAGATE_ERROR(previewConsumerThread.shutdown());
-
-    // Shut down Argus.
-    cameraProvider.reset();
-
-    // Shut down the window (destroys window's EGLSurface).
-    window.shutdown();
-
-    // Cleanup the EGL display
-    PROPAGATE_ERROR(g_display.cleanup());
-
+    //iSession->stopRepeat is cleaned with captureSession RAII
     return true;
 }
 
diff --git a/public/samples/userAutoWhiteBalance/main.cpp b/public/samples/userAutoWhiteBalance/main.cpp
old mode 100644
new mode 100755
index 8724ee7..2de9159
--- a/public/samples/userAutoWhiteBalance/main.cpp
+++ b/public/samples/userAutoWhiteBalance/main.cpp
@@ -83,6 +83,51 @@ protected:
     Value<bool> m_useAverageMap;
 };
 
+/**
+ * RAII class for app teardown
+ */
+class UserAutoWhiteBalanceTeardown
+{
+public:
+    CameraProvider* m_cameraProvider;
+    PreviewConsumerThread* m_previewConsumerThread;
+    OutputStream* m_stream;
+
+    UserAutoWhiteBalanceTeardown()
+    {
+        m_cameraProvider = NULL;
+        m_previewConsumerThread = NULL;
+        m_stream = NULL;
+    }
+
+    ~UserAutoWhiteBalanceTeardown()
+    {
+        shutdown();
+    }
+
+private:
+    void shutdown()
+    {
+        // Destroy the output streams (stops consumer threads).
+        if (m_stream != NULL)
+            m_stream->destroy();
+
+        // Wait for the consumer threads to complete.
+        if (m_previewConsumerThread != NULL)
+            PROPAGATE_ERROR_CONTINUE(m_previewConsumerThread->shutdown());
+
+        // Shut down Argus.
+        if (m_cameraProvider != NULL)
+            m_cameraProvider->destroy();
+
+        // Shut down the window (destroys window's EGLSurface).
+        Window::getInstance().shutdown();
+
+        // Cleanup the EGL display
+        PROPAGATE_ERROR_CONTINUE(g_display.cleanup());
+    }
+};
+
 /*
  * Program: userAutoWhiteBalance
  * Function: To display 101 preview images to the device display to illustrate a
@@ -92,12 +137,12 @@ protected:
 
 static bool execute(const UserAutoWhiteBalanceSampleOptions& options)
 {
+    UserAutoWhiteBalanceTeardown appTearDown;
     BayerTuple<float> precedingAverages(1.0f, 1.5f, 1.5f, 1.5f);
 
     // Initialize the window and EGL display.
-    Window &window = Window::getInstance();
-    window.setWindowRect(options.windowRect());
-    PROPAGATE_ERROR(g_display.initialize(window.getEGLNativeDisplay()));
+    Window::getInstance().setWindowRect(options.windowRect());
+    PROPAGATE_ERROR(g_display.initialize(Window::getInstance().getEGLNativeDisplay()));
 
     /*
      * Set up Argus API Framework, identify available camera devices, create
@@ -105,14 +150,14 @@ static bool execute(const UserAutoWhiteBalanceSampleOptions& options)
      * queue for completed events
      */
 
-    UniqueObj<CameraProvider> cameraProvider(CameraProvider::create());
-    ICameraProvider *iCameraProvider = interface_cast<ICameraProvider>(cameraProvider);
+    appTearDown.m_cameraProvider = CameraProvider::create();
+    ICameraProvider *iCameraProvider = interface_cast<ICameraProvider>(appTearDown.m_cameraProvider);
     EXIT_IF_NULL(iCameraProvider, "Cannot get core camera provider interface");
     printf("Argus Version: %s\n", iCameraProvider->getVersion().c_str());
 
     // Get the selected camera device and sensor mode.
     CameraDevice* cameraDevice = ArgusHelpers::getCameraDevice(
-            cameraProvider.get(), options.cameraDeviceIndex());
+        appTearDown.m_cameraProvider, options.cameraDeviceIndex());
     if (!cameraDevice)
         ORIGINATE_ERROR("Selected camera device is not available");
     SensorMode* sensorMode = ArgusHelpers::getSensorMode(cameraDevice, options.sensorModeIndex());
@@ -122,7 +167,7 @@ static bool execute(const UserAutoWhiteBalanceSampleOptions& options)
 
     // Create the CaptureSession using the selected device.
     UniqueObj<CaptureSession> captureSession(iCameraProvider->createCaptureSession(cameraDevice));
-    ICaptureSession *iSession = interface_cast<ICaptureSession>(captureSession);
+    ICaptureSession* iSession = interface_cast<ICaptureSession>(captureSession);
     EXIT_IF_NULL(iSession, "Cannot get Capture Session Interface");
 
     IEventProvider *iEventProvider = interface_cast<IEventProvider>(captureSession);
@@ -130,6 +175,10 @@ static bool execute(const UserAutoWhiteBalanceSampleOptions& options)
 
     std::vector<EventType> eventTypes;
     eventTypes.push_back(EVENT_TYPE_CAPTURE_COMPLETE);
+    eventTypes.push_back(EVENT_TYPE_ERROR);
+    /* Seems there is bug in Argus, which drops EVENT_TYPE_ERROR if all
+    3 events are not set. Set it for now */
+    eventTypes.push_back(EVENT_TYPE_CAPTURE_STARTED);
     UniqueObj<EventQueue> queue(iEventProvider->createEventQueue(eventTypes));
     IEventQueue *iQueue = interface_cast<IEventQueue>(queue);
     EXIT_IF_NULL(iQueue, "event queue interface is NULL");
@@ -145,7 +194,7 @@ static bool execute(const UserAutoWhiteBalanceSampleOptions& options)
      */
 
     UniqueObj<OutputStreamSettings> streamSettings(
-            iSession->createOutputStreamSettings(STREAM_TYPE_EGL));
+        iSession->createOutputStreamSettings(STREAM_TYPE_EGL));
 
     IEGLOutputStreamSettings *iEGLStreamSettings =
         interface_cast<IEGLOutputStreamSettings>(streamSettings);
@@ -156,15 +205,15 @@ static bool execute(const UserAutoWhiteBalanceSampleOptions& options)
                                                        options.windowRect().height()));
     iEGLStreamSettings->setEGLDisplay(g_display.get());
 
-    UniqueObj<OutputStream> stream(iSession->createOutputStream(streamSettings.get()));
+    appTearDown.m_stream = iSession->createOutputStream(streamSettings.get());
 
-    IEGLOutputStream *iEGLOutputStream = interface_cast<IEGLOutputStream>(stream);
+    IEGLOutputStream *iEGLOutputStream = interface_cast<IEGLOutputStream>(appTearDown.m_stream);
     EXIT_IF_NULL(iEGLOutputStream, "Cannot get IEGLOutputStream Interface");
 
-    PreviewConsumerThread previewConsumerThread(
+    appTearDown.m_previewConsumerThread = new PreviewConsumerThread(
         iEGLOutputStream->getEGLDisplay(), iEGLOutputStream->getEGLStream());
-    PROPAGATE_ERROR(previewConsumerThread.initialize());
-    PROPAGATE_ERROR(previewConsumerThread.waitRunning());
+    PROPAGATE_ERROR(appTearDown.m_previewConsumerThread->initialize());
+    PROPAGATE_ERROR(appTearDown.m_previewConsumerThread->waitRunning());
 
     UniqueObj<Request> request(iSession->createRequest(CAPTURE_INTENT_PREVIEW));
     IRequest *iRequest = interface_cast<IRequest>(request);
@@ -176,7 +225,7 @@ static bool execute(const UserAutoWhiteBalanceSampleOptions& options)
     EXIT_IF_NULL(iSourceSettings, "Failed to get source settings interface");
     iSourceSettings->setSensorMode(sensorMode);
 
-    EXIT_IF_NOT_OK(iRequest->enableOutputStream(stream.get()),
+    EXIT_IF_NOT_OK(iRequest->enableOutputStream(appTearDown.m_stream),
         "Failed to enable stream in capture request");
 
     IAutoControlSettings* iAutoControlSettings =
@@ -205,184 +254,183 @@ static bool execute(const UserAutoWhiteBalanceSampleOptions& options)
     while (frameCaptureLoop < options.frameCount())
     {
         // Keep PREVIEW display window serviced
-        window.pollEvents();
+        Window::getInstance().pollEvents();
 
-        const uint64_t ONE_SECOND = 1000000000;
-        iEventProvider->waitForEvents(queue.get(), ONE_SECOND);
+        const uint64_t FIVE_SECONDS = 5000000000;
+        iEventProvider->waitForEvents(queue.get(), FIVE_SECONDS);
         EXIT_IF_TRUE(iQueue->getSize() == 0, "No events in queue");
 
         frameCaptureLoop += iQueue->getSize();
 
         const Event* event = iQueue->getEvent(iQueue->getSize() - 1);
-        const IEventCaptureComplete *iEventCaptureComplete
-            = interface_cast<const IEventCaptureComplete>(event);
-        EXIT_IF_NULL(iEventCaptureComplete, "Failed to get EventCaptureComplete Interface");
-
-        const CaptureMetadata *metaData = iEventCaptureComplete->getMetadata();
-        const ICaptureMetadata* iMetadata = interface_cast<const ICaptureMetadata>(metaData);
-
-        EXIT_IF_NULL(iMetadata, "Failed to get CaptureMetadata Interface");
-
-        BayerTuple<float> bayerTotals(0.0f);
-        BayerTuple<float> bayerAverages(0.0f);
-        if (!options.useAverageMap())
-        {
-            const IBayerHistogram* bayerHistogram =
-                interface_cast<const IBayerHistogram>(iMetadata->getBayerHistogram());
-            const Ext::INonLinearHistogram* iNonLinearHistogram =
-                interface_cast<const Ext::INonLinearHistogram>(iMetadata->getBayerHistogram());
-
-            std::vector< BayerTuple<uint32_t> > histogram;
-            std::vector< BayerTuple<float> > binValues;
-            EXIT_IF_NOT_OK(bayerHistogram->getHistogram(&histogram), "Failed to get histogram");
-
-            if (iNonLinearHistogram)
-            {
-                EXIT_IF_NOT_OK(iNonLinearHistogram->getHistogramBinValues(
-                                                &binValues), "Failed to get linear bin values");
-            }
-            uint32_t histogramClippedCount =  histogram.size() *
-                                                        (1.0f - BAYER_HISTOGRAM_CLIP_PERCENTILE);
-            for (int channel = 0; channel < BAYER_CHANNEL_COUNT; channel++)
-            {
-                for (uint32_t bin = 0; bin < histogramClippedCount; bin++)
+        const IEvent* iEvent = interface_cast<const IEvent>(event);
+        if (!iEvent)
+            printf("Error : Failed to get IEvent interface\n");
+        else {
+            if (iEvent->getEventType() == EVENT_TYPE_CAPTURE_COMPLETE) {
+                const IEventCaptureComplete* iEventCaptureComplete =
+                    interface_cast<const IEventCaptureComplete>(event);
+                EXIT_IF_NULL(iEventCaptureComplete, "Failed to get EventCaptureComplete Interface");
+
+                const CaptureMetadata* metaData = iEventCaptureComplete->getMetadata();
+                const ICaptureMetadata* iMetadata = interface_cast<const ICaptureMetadata>(metaData);
+
+                EXIT_IF_NULL(iMetadata, "Failed to get CaptureMetadata Interface");
+
+                BayerTuple<float> bayerTotals(0.0f);
+                BayerTuple<float> bayerAverages(0.0f);
+                if (!options.useAverageMap())
                 {
-                    float bayerValue = (iNonLinearHistogram) ?
-                                       (binValues[bin][channel] * histogram.size()) : bin;
+                    const IBayerHistogram* bayerHistogram =
+                        interface_cast<const IBayerHistogram>(iMetadata->getBayerHistogram());
+                    const Ext::INonLinearHistogram* iNonLinearHistogram =
+                        interface_cast<const Ext::INonLinearHistogram>(iMetadata->getBayerHistogram());
 
-                    bayerTotals[channel]   += histogram[bin][channel];
-                    bayerAverages[channel] += histogram[bin][channel] * bayerValue;
-                }
-                if (bayerTotals[channel])
-                    bayerAverages[channel] /= bayerTotals[channel];
-            }
+                    std::vector< BayerTuple<uint32_t> > histogram;
+                    std::vector< BayerTuple<float> > binValues;
+                    EXIT_IF_NOT_OK(bayerHistogram->getHistogram(&histogram), "Failed to get histogram");
 
-            printf("Histogram ");
-        }
-        else
-        {
-            const Ext::IBayerAverageMap* iBayerAverageMap =
-                interface_cast<const Ext::IBayerAverageMap>(metaData);
-            EXIT_IF_NULL(iBayerAverageMap, "Failed to get IBayerAverageMap interface");
-            Array2D< BayerTuple<float> > averages;
-            EXIT_IF_NOT_OK(iBayerAverageMap->getAverages(&averages),
-                "Failed to get averages");
-            Array2D< BayerTuple<uint32_t> > clipCounts;
-            EXIT_IF_NOT_OK(iBayerAverageMap->getClipCounts(&clipCounts),
-                "Failed to get clip counts");
-            uint32_t pixelsPerBinPerChannel =
-                iBayerAverageMap->getBinSize().width() *
-                iBayerAverageMap->getBinSize().height() /
-                BAYER_CHANNEL_COUNT;
-            EXIT_IF_NULL(pixelsPerBinPerChannel, "Zero pixels per bin channel");
-
-            // Using the BayerAverageMap, get the average instensity across the checked area
-            uint32_t usedBins = 0;
-            for (uint32_t x = 0; x < averages.size().width(); x++)
-            {
-                for (uint32_t y = 0; y < averages.size().height(); y++)
+                    if (iNonLinearHistogram)
+                    {
+                        EXIT_IF_NOT_OK(iNonLinearHistogram->getHistogramBinValues(
+                                                        &binValues), "Failed to get linear bin values");
+                    }
+                    uint32_t histogramClippedCount = histogram.size() *
+                                                        (1.0f - BAYER_HISTOGRAM_CLIP_PERCENTILE);
+                    for (int channel = 0; channel < BAYER_CHANNEL_COUNT; channel++)
+                    {
+                        for (uint32_t bin = 0; bin < histogramClippedCount; bin++)
+                        {
+                            float bayerValue = (iNonLinearHistogram) ?
+                                                (binValues[bin][channel] * histogram.size()) : bin;
+
+                            bayerTotals[channel] += histogram[bin][channel];
+                            bayerAverages[channel] += histogram[bin][channel] * bayerValue;
+                        }
+                        if (bayerTotals[channel])
+                            bayerAverages[channel] /= bayerTotals[channel];
+                    }
+
+                    printf("Histogram ");
+                }
+                else
                 {
+                    const Ext::IBayerAverageMap* iBayerAverageMap =
+                        interface_cast<const Ext::IBayerAverageMap>(metaData);
+                    EXIT_IF_NULL(iBayerAverageMap, "Failed to get IBayerAverageMap interface");
+                    Array2D< BayerTuple<float> > averages;
+                    EXIT_IF_NOT_OK(iBayerAverageMap->getAverages(&averages),
+                        "Failed to get averages");
+                    Array2D< BayerTuple<uint32_t> > clipCounts;
+                    EXIT_IF_NOT_OK(iBayerAverageMap->getClipCounts(&clipCounts),
+                        "Failed to get clip counts");
+                    uint32_t pixelsPerBinPerChannel =
+                        iBayerAverageMap->getBinSize().width() *
+                        iBayerAverageMap->getBinSize().height() /
+                        BAYER_CHANNEL_COUNT;
+                    EXIT_IF_NULL(pixelsPerBinPerChannel, "Zero pixels per bin channel");
+
+                    // Using the BayerAverageMap, get the average instensity across the checked area
+                    uint32_t usedBins = 0;
+                    for (uint32_t x = 0; x < averages.size().width(); x++)
+                    {
+                        for (uint32_t y = 0; y < averages.size().height(); y++)
+                        {
+                            /*
+                             * Bins with excessively high clip counts many contain
+                             * misleading averages, since clipped pixels are ignored
+                             * in the averages, and so these bins are ignored.
+                             *
+                             */
+                            if ((float)clipCounts(x, y).r() / pixelsPerBinPerChannel
+                                    <= BAYER_CLIP_COUNT_MAX &&
+                                (float)clipCounts(x, y).gEven() / pixelsPerBinPerChannel
+                                    <= BAYER_CLIP_COUNT_MAX &&
+                                (float)clipCounts(x, y).gOdd() / pixelsPerBinPerChannel
+                                    <= BAYER_CLIP_COUNT_MAX &&
+                                (float)clipCounts(x, y).b() / pixelsPerBinPerChannel
+                                    <= BAYER_CLIP_COUNT_MAX)
+                            {
+                                bayerTotals += averages(x, y);
+                                usedBins++;
+                            }
+                        }
+                    }
+
+                    EXIT_IF_NULL(usedBins, "No used bins");
+
                     /*
-                     * Bins with excessively high clip counts many contain
-                     * misleading averages, since clipped pixels are ignored
-                     * in the averages, and so these bins are ignored.
-                     *
+                     * This check is to determine if enough BayerAverageMap samples
+                     * have been collected to give a valid enough evaluation of the
+                     * white balance adjustment.  If not enough samples, then the
+                     * most previous valid results are used.  If valid, then the valid
+                     * set is stored for future use.
                      */
-                    if ((float)clipCounts(x, y).r() / pixelsPerBinPerChannel
-                            <= BAYER_CLIP_COUNT_MAX &&
-                        (float)clipCounts(x, y).gEven() / pixelsPerBinPerChannel
-                            <= BAYER_CLIP_COUNT_MAX &&
-                        (float)clipCounts(x, y).gOdd() / pixelsPerBinPerChannel
-                            <= BAYER_CLIP_COUNT_MAX &&
-                        (float)clipCounts(x, y).b() / pixelsPerBinPerChannel
-                            <= BAYER_CLIP_COUNT_MAX)
+                    if ((float)usedBins / (averages.size().width() * averages.size().height()) <
+                        (1.0f - BAYER_MISSING_SAMPLE_TOLERANCE))
                     {
-                        bayerTotals += averages(x, y);
-                        usedBins++;
+                        printf("Clipped sensor sample percentage of %0.1f%%"
+                            " exceed tolerance of %0.1f%%\n"
+                            "Using last valid BayerAverageMap intensity values\n",
+                            (1.0f - (float)usedBins /
+                            (averages.size().width() * averages.size().height())) * 100,
+                            BAYER_MISSING_SAMPLE_TOLERANCE * 100);
+                        bayerAverages = precedingAverages;
                     }
+                    else
+                    {
+                        for (int channel = 0; channel < BAYER_CHANNEL_COUNT; channel++)
+                        {
+                            bayerAverages[channel] = bayerTotals[channel] / usedBins;
+                            precedingAverages[channel] = bayerAverages[channel];
+                        }
+                    }
+                    printf("BayerAverageMap ");
                 }
-            }
 
-            EXIT_IF_NULL(usedBins, "No used bins");
-
-            /*
-             * This check is to determine if enough BayerAverageMap samples
-             * have been collected to give a valid enough evaluation of the
-             * white balance adjustment.  If not enough samples, then the
-             * most previous valid results are used.  If valid, then the valid
-             * set is stored for future use.
-             */
-            if ((float)usedBins / (averages.size().width() * averages.size().height()) <
-                ( 1.0f - BAYER_MISSING_SAMPLE_TOLERANCE ))
-            {
-                printf("Clipped sensor sample percentage of %0.1f%%"
-                    " exceed tolerance of %0.1f%%\n"
-                    "Using last valid BayerAverageMap intensity values\n",
-                    (1.0f - (float)usedBins /
-                        (averages.size().width() * averages.size().height())) * 100,
-                    BAYER_MISSING_SAMPLE_TOLERANCE * 100);
-                bayerAverages = precedingAverages;
-            }
-            else
-            {
-                for (int channel=0; channel<BAYER_CHANNEL_COUNT; channel++)
+                float maxGain = 0;
+                for (int channel = 0; channel < BAYER_CHANNEL_COUNT; channel++)
                 {
-                    bayerAverages[channel] = bayerTotals[channel] / usedBins;
-                    precedingAverages[channel] = bayerAverages[channel];
+                    maxGain = std::max(maxGain, bayerAverages[channel]);
+                }
+                float whiteBalanceGains[BAYER_CHANNEL_COUNT];
+                for (int channel = 0; channel < BAYER_CHANNEL_COUNT; channel++)
+                {
+                    whiteBalanceGains[channel] = maxGain / bayerAverages[channel];
                 }
-            }
-            printf("BayerAverageMap ");
-        }
 
-        float maxGain = 0;
-        for (int channel = 0; channel < BAYER_CHANNEL_COUNT; channel++)
-        {
-            maxGain = std::max(maxGain, bayerAverages[channel]);
-        }
-        float whiteBalanceGains[BAYER_CHANNEL_COUNT];
-        for (int channel = 0; channel < BAYER_CHANNEL_COUNT; channel++)
-        {
-            whiteBalanceGains[channel] = maxGain / bayerAverages[channel];
+                printf("Intensity: r:%0.3f gO:%0.3f gE:%0.3f b:%0.3f   "
+                    "WBGains: r:%0.3f gO:%0.3f gE:%0.3f b:%0.3f\n",
+                    bayerAverages[0],
+                    bayerAverages[1],
+                    bayerAverages[2],
+                    bayerAverages[3],
+                    whiteBalanceGains[0],
+                    whiteBalanceGains[1],
+                    whiteBalanceGains[2],
+                    whiteBalanceGains[3]);
+
+                BayerTuple<float> bayerGains(whiteBalanceGains[0], whiteBalanceGains[1],
+                    whiteBalanceGains[2], whiteBalanceGains[3]);
+
+                iAutoControlSettings->setWbGains(bayerGains);
+                iAutoControlSettings->setAwbMode(AWB_MODE_MANUAL);
+
+                EXIT_IF_NOT_OK(iSession->repeat(request.get()), "Unable to submit repeat() request");
+            } else if (iEvent->getEventType() == EVENT_TYPE_CAPTURE_STARTED) {
+                /* ToDo: Remove the empty after the bug is fixed */
+                continue;
+            } else if (iEvent->getEventType() == EVENT_TYPE_ERROR) {
+                const IEventError* iEventError =
+                    interface_cast<const IEventError>(event);
+                EXIT_IF_NOT_OK(iEventError->getStatus(), "ERROR event");
+            } else {
+                printf("WARNING: Unknown event. Continue\n");
+            }
         }
-
-        printf("Intensity: r:%0.3f gO:%0.3f gE:%0.3f b:%0.3f   "
-               "WBGains: r:%0.3f gO:%0.3f gE:%0.3f b:%0.3f\n",
-               bayerAverages[0],
-               bayerAverages[1],
-               bayerAverages[2],
-               bayerAverages[3],
-               whiteBalanceGains[0],
-               whiteBalanceGains[1],
-               whiteBalanceGains[2],
-               whiteBalanceGains[3]);
-
-        BayerTuple<float> bayerGains(whiteBalanceGains[0], whiteBalanceGains[1],
-                                     whiteBalanceGains[2], whiteBalanceGains[3]);
-
-        iAutoControlSettings->setWbGains(bayerGains);
-        iAutoControlSettings->setAwbMode(AWB_MODE_MANUAL);
-
-        EXIT_IF_NOT_OK(iSession->repeat(request.get()), "Unable to submit repeat() request");
     }
 
-    iSession->stopRepeat();
-    iSession->waitForIdle();
-
-    // Destroy the output streams (stops consumer threads).
-    stream.reset();
-
-    // Wait for the consumer threads to complete.
-    PROPAGATE_ERROR(previewConsumerThread.shutdown());
-
-    // Shut down Argus.
-    cameraProvider.reset();
-
-    // Shut down the window (destroys window's EGLSurface).
-    window.shutdown();
-
-    // Cleanup the EGL display
-    PROPAGATE_ERROR(g_display.cleanup());
-
+    //iSession->stopRepeat is cleaned with captureSession RAII
     return true;
 }
 
-- 
2.7.4

