/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "vie_autotest.h"

#include "common_types.h"
#include "engine_configurations.h"
#include "gflags/gflags.h"
#include "tb_interfaces.h"
#include "tb_video_channel.h"
#include "tick_util.h"
#include "vie_autotest_defines.h"
#include "video_capture_factory.h"
#include "vie_base.h"
#include "vie_capture.h"
#include "vie_codec.h"
#include "vie_network.h"
#include "vie_render.h"
#include "vie_rtp_rtcp.h"
#include "voe_base.h"

DEFINE_bool(capture_test_ensure_resolution_alignment_in_capture_device, true,
            "If true, we will give resolutions slightly below a reasonable "
            "value to test the camera's ability to choose a good resolution. "
            "If false, we will provide reasonable resolutions instead.");

class CaptureObserver: public webrtc::ViECaptureObserver
{
public:
    CaptureObserver() :
        _brightness(webrtc::Normal),
        _alarm(webrtc::AlarmCleared),
        _frameRate(0) {}

    virtual void BrightnessAlarm(const int captureId,
                                 const webrtc::Brightness brightness)
    {
        _brightness = brightness;
        switch (brightness)
        {
            case webrtc::Normal:
                ViETest::Log("  BrightnessAlarm Normal");
                break;
            case webrtc::Bright:
                ViETest::Log("  BrightnessAlarm Bright");
                break;
            case webrtc::Dark:
                ViETest::Log("  BrightnessAlarm Dark");
                break;
            default:
                assert(!"Unknown brightness alarm");
        }
    }

    virtual void CapturedFrameRate(const int captureId,
                                   const unsigned char frameRate)
    {
        ViETest::Log("  CapturedFrameRate %u", frameRate);
        _frameRate = frameRate;
    }

    virtual void NoPictureAlarm(const int captureId,
                                const webrtc::CaptureAlarm alarm)
    {
        _alarm = alarm;
        if (alarm == webrtc::AlarmRaised)
        {
            ViETest::Log("NoPictureAlarm CARaised.");
        }
        else
        {
            ViETest::Log("NoPictureAlarm CACleared.");
        }
    }

    webrtc::Brightness _brightness;
    webrtc::CaptureAlarm _alarm;
    unsigned char _frameRate;
};

class CaptureEffectFilter: public webrtc::ViEEffectFilter
{
public:
    CaptureEffectFilter(unsigned int reqWidth, unsigned int reqHeight,
                        int& numberOfErrors) :
        _numberOfCapturedFrames(0),
        _reqWidth(reqWidth),
        _reqHeight(reqHeight),
        _numberOfErrors(numberOfErrors)
    {
    }
    // Implements ViEEffectFilter
    virtual int Transform(int size, unsigned char* frameBuffer,
                          unsigned int timeStamp90KHz, unsigned int width,
                          unsigned int height)
    {
        _numberOfErrors += ViETest::TestError(
            frameBuffer != 0
            && width == _reqWidth
            && height == _reqHeight,
            "ERROR: %s at line %d", __FUNCTION__, __LINE__);
        ++_numberOfCapturedFrames;
        return 0;
    }

    int _numberOfCapturedFrames;

protected:
    unsigned int _reqWidth;
    unsigned int _reqHeight;
    int& _numberOfErrors;
};

int ViEAutoTest::ViECaptureStandardTest()
{
    int numberOfErrors = 0;
    ViETest::Log(" ");
    ViETest::Log("========================================");
    ViETest::Log(" ViECapture StandardTest Test\n");

    //***************************************************************
    //	Begin create/initialize WebRTC Video Engine for testing
    //***************************************************************


    //***************************************************************
    //	Engine ready. Begin testing class
    //***************************************************************


    int error = 0;
    TbInterfaces ViE("ViECaptureStandardTest", numberOfErrors);

    webrtc::VideoCaptureModule::DeviceInfo* devInfo =
        webrtc::VideoCaptureFactory::CreateDeviceInfo(0);

    int numberOfCaptureDevices = devInfo->NumberOfDevices();
    ViETest::Log("Number of capture devices %d", numberOfCaptureDevices);
    numberOfErrors += ViETest::TestError(numberOfCaptureDevices > 0,
                                         "ERROR: %s at line %d", __FUNCTION__,
                                         __LINE__);

    int captureDeviceId[10];
    webrtc::VideoCaptureModule* vcpms[10];
    memset(vcpms, 0, sizeof(vcpms));

    //Check capabilities
    for (int deviceIndex = 0;
         deviceIndex < numberOfCaptureDevices;
         ++deviceIndex)
    {
        WebRtc_UWord8 deviceName[128];
        WebRtc_UWord8 deviceUniqueName[512];

        error = devInfo->GetDeviceName(deviceIndex, deviceName,
                                       sizeof(deviceName), deviceUniqueName,
                                       sizeof(deviceUniqueName));
        numberOfErrors += ViETest::TestError(error == 0,
                                             "ERROR: %s at line %d",
                                             __FUNCTION__, __LINE__);
        ViETest::Log("Found capture device %s\nUnique name %s", deviceName,
                     deviceUniqueName);

// not supported on MAC (is part of capture capabilites
#if !defined(WEBRTC_LINUX) && !defined(WEBRTC_MAC_INTEL)
        error = ViE.capture->ShowCaptureSettingsDialogBox(
            (char*) deviceUniqueName,
            (unsigned int) (strlen((char*) deviceUniqueName)),
            "WebRTCViECapture StandardTest");
        numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                             __FUNCTION__, __LINE__);
#endif

#if !defined(WEBRTC_MAC_INTEL) // these functions will return -1
        unsigned int numberOfCapabilities =
            devInfo->NumberOfCapabilities(deviceUniqueName);
        numberOfErrors += ViETest::TestError(numberOfCapabilities > 0,
                                             "ERROR: %s at line %d",
                                             __FUNCTION__, __LINE__);

        for (unsigned int capIndex = 0;
             capIndex < numberOfCapabilities;
             ++capIndex)
        {
            webrtc::VideoCaptureCapability capability;
            error = devInfo->GetCapability(deviceUniqueName, capIndex,
                                           capability);
            numberOfErrors += ViETest::TestError(error == 0,
                                                 "ERROR: %s at line %d",
                                                 __FUNCTION__, __LINE__);
            ViETest::Log("Capture capability %d (of %u)", capIndex + 1,
                         numberOfCapabilities);
            ViETest::Log("witdh %d, height %d, frame rate %d",
                         capability.width, capability.height, capability.maxFPS);
            ViETest::Log("expected delay %d, color type %d, encoding %d",
                         capability.expectedCaptureDelay, capability.rawType,
                         capability.codecType);
            numberOfErrors += ViETest::TestError(
                capability.width > 0
                && capability.height > 0
                && capability.maxFPS >= 0
                && capability.expectedCaptureDelay > 0,
                "ERROR: %s at line %d", __FUNCTION__, __LINE__);
        }
#endif
    }
    // Capture Capability Functions are not supported on WEBRTC_MAC_INTEL.
#if !defined(WEBRTC_MAC_INTEL)

    // Check allocation. Try to allocate them all after each other.
    for (int deviceIndex = 0;
         deviceIndex < numberOfCaptureDevices;
         ++deviceIndex)
    {
        WebRtc_UWord8 deviceName[128];
        WebRtc_UWord8 deviceUniqueName[512];

        error = devInfo->GetDeviceName(deviceIndex, deviceName,
                                       sizeof(deviceName), deviceUniqueName,
                                       sizeof(deviceUniqueName));
        numberOfErrors += ViETest::TestError(error == 0,
                                             "ERROR: %s at line %d",
                                             __FUNCTION__, __LINE__);

        webrtc::VideoCaptureModule* vcpm =
            webrtc::VideoCaptureFactory::Create(
                deviceIndex, deviceUniqueName);
        vcpm->AddRef();
        numberOfErrors += ViETest::TestError(vcpm != NULL,
                                             "ERROR: %s at line %d",
                                             __FUNCTION__, __LINE__);
        vcpms[deviceIndex] = vcpm;

        error = ViE.capture->AllocateCaptureDevice(
                                            *vcpm, captureDeviceId[deviceIndex]);
        numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                             __FUNCTION__, __LINE__);

        webrtc::VideoCaptureCapability capability;
        error = devInfo->GetCapability(deviceUniqueName, 0, capability);

        // Test that the camera select the closest capability to the selected
        // width and height.
        CaptureEffectFilter filter(capability.width, capability.height,
                                   numberOfErrors);
        error = ViE.image_process->RegisterCaptureEffectFilter(
                                        captureDeviceId[deviceIndex], filter);
        numberOfErrors += ViETest::TestError(error == 0,
                                             "ERROR: %s at line %d",
                                             __FUNCTION__, __LINE__);

        ViETest::Log("Testing Device %s capability width %d  height %d",
                     deviceUniqueName, capability.width, capability.height);

        if (FLAGS_capture_test_ensure_resolution_alignment_in_capture_device) {
          // This tests that the capture device properly aligns to a
          // multiple of 16 (or at least 8).
          capability.height = capability.height - 2;
          capability.width  = capability.width  - 2;
        }

        webrtc::CaptureCapability vieCapability;
        vieCapability.width = capability.width;
        vieCapability.height = capability.height;
        vieCapability.codecType = capability.codecType;
        vieCapability.maxFPS = capability.maxFPS;
        vieCapability.rawType = capability.rawType;

        error = ViE.capture->StartCapture(captureDeviceId[deviceIndex],
                                                vieCapability);
        numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                             __FUNCTION__, __LINE__);
        webrtc::TickTime startTime = webrtc::TickTime::Now();

        while (filter._numberOfCapturedFrames < 10
               && (webrtc::TickTime::Now() - startTime).Milliseconds() < 10000)
        {
            AutoTestSleep(100);
        }
        numberOfErrors += ViETest::TestError(filter._numberOfCapturedFrames
            >= 10, "ERROR: %s at line %d", __FUNCTION__, __LINE__);
        error = ViE.image_process->DeregisterCaptureEffectFilter(
            captureDeviceId[deviceIndex]);

#ifdef WEBRTC_ANDROID // Can only allocate one camera at the time on Android
        error = ViE.capture->StopCapture(captureDeviceId[deviceIndex]);
        numberOfErrors += ViETest::TestError(error==0, "ERROR: %s at line %d",
                                             __FUNCTION__, __LINE__);

        error = ViE.capture->ReleaseCaptureDevice(
            captureDeviceId[deviceIndex]);
        numberOfErrors += ViETest::TestError(error==0, "ERROR: %s at line %d",
                                             __FUNCTION__, __LINE__);
#endif
    }

    //***************************************************************
    //	Testing finished. Tear down Video Engine
    //***************************************************************


    // stop all started capture devices
    for (int deviceIndex = 0; deviceIndex < numberOfCaptureDevices; ++deviceIndex)
    {
        error = ViE.capture->StopCapture(captureDeviceId[deviceIndex]);
#ifdef WEBRTC_ANDROID
        // Camera already stoped on Android since we can only allocate one
        // camera at the time.
        numberOfErrors += ViETest::TestError(error==-1, "ERROR: %s at line %d",
                                             __FUNCTION__, __LINE__);
#else
        numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                             __FUNCTION__, __LINE__);
#endif

        error = ViE.capture->ReleaseCaptureDevice(
            captureDeviceId[deviceIndex]);
#ifdef WEBRTC_ANDROID
        // Camera already stoped on Android since we can only allocate one
        // camera at the time
        numberOfErrors += ViETest::TestError(error==-1, "ERROR: %s at line %d",
                                             __FUNCTION__, __LINE__);
#else
        numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                             __FUNCTION__, __LINE__);
#endif
        vcpms[deviceIndex]->Release();
    }
#endif
    if (numberOfErrors > 0)
    {
        // Test failed
        ViETest::Log(" ");
        ViETest::Log(" ERROR ViECapture Standard Test FAILED!");
        ViETest::Log(" Number of errors: %d", numberOfErrors);
        ViETest::Log("========================================");
        ViETest::Log(" ");
        return numberOfErrors;
    }
    delete devInfo;

    ViETest::Log(" ");
    ViETest::Log(" ViECapture Standard Test PASSED!");
    ViETest::Log("========================================");
    ViETest::Log(" ");

    return 0;
}

int ViEAutoTest::ViECaptureExtendedTest()
{

    // Test
    int numberOfErrors = 0;
    numberOfErrors += ViECaptureStandardTest();
    numberOfErrors += ViECaptureAPITest();
    numberOfErrors += ViECaptureExternalCaptureTest();

    return 0;
}

int ViEAutoTest::ViECaptureAPITest()
{
    int numberOfErrors = 0;
    ViETest::Log(" ");
    ViETest::Log("========================================");
    ViETest::Log(" ViECapture API Test\n");

    //***************************************************************
    //	Begin create/initialize WebRTC Video Engine for testing
    //***************************************************************


    //***************************************************************
    //	Engine ready. Begin testing class
    //***************************************************************

    int error = 0;
    TbInterfaces ViE("ViECaptureAPITest", numberOfErrors);

    ViE.capture->NumberOfCaptureDevices();

    WebRtc_UWord8 deviceName[128];
    WebRtc_UWord8 deviceUniqueName[512];
    int captureId = 0;

    webrtc::VideoCaptureModule::DeviceInfo* devInfo =
        webrtc::VideoCaptureFactory::CreateDeviceInfo(0);
    numberOfErrors += ViETest::TestError(devInfo != NULL,
                                         "ERROR: %s at line %d", __FUNCTION__,
                                         __LINE__);

    // Get the first capture device
    error = devInfo->GetDeviceName(0, deviceName, sizeof(deviceName),
                                   deviceUniqueName, sizeof(deviceUniqueName));
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    webrtc::VideoCaptureModule* vcpm =
        webrtc::VideoCaptureFactory::Create(
            0, deviceUniqueName);
    vcpm->AddRef();
    numberOfErrors += ViETest::TestError(vcpm != NULL, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Allocate capture device
    error = ViE.capture->AllocateCaptureDevice(*vcpm, captureId);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Start the capture device
    error = ViE.capture->StartCapture(captureId);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Start again. Should fail
    error = ViE.capture->StartCapture(captureId);
    numberOfErrors += ViETest::TestError(error == -1, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);
    numberOfErrors += ViETest::TestError(ViE.LastError()
        == kViECaptureDeviceAlreadyStarted, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Start invalid capture device
    error = ViE.capture->StartCapture(captureId + 1);
    numberOfErrors += ViETest::TestError(error == -1, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);
    numberOfErrors += ViETest::TestError(ViE.LastError()
        == kViECaptureDeviceDoesnNotExist, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Stop invalide capture device
    error = ViE.capture->StopCapture(captureId + 1);
    numberOfErrors += ViETest::TestError(error == -1, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);
    numberOfErrors += ViETest::TestError(ViE.LastError()
        == kViECaptureDeviceDoesnNotExist, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Stop the capture device
    error = ViE.capture->StopCapture(captureId);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Stop the capture device again
    error = ViE.capture->StopCapture(captureId);
    numberOfErrors += ViETest::TestError(error == -1, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);
    numberOfErrors += ViETest::TestError(ViE.LastError()
        == kViECaptureDeviceNotStarted, "ERROR: %s at line %d", __FUNCTION__,
                                         __LINE__);

    // Connect to invalid channel
    error = ViE.capture->ConnectCaptureDevice(captureId, 0);
    numberOfErrors += ViETest::TestError(error == -1, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);
    numberOfErrors += ViETest::TestError(ViE.LastError()
        == kViECaptureDeviceInvalidChannelId, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    tbVideoChannel channel(ViE, numberOfErrors);

    // Connect invalid captureId
    error = ViE.capture->ConnectCaptureDevice(captureId + 1,
                                                    channel.videoChannel);
    numberOfErrors += ViETest::TestError(error == -1, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);
    numberOfErrors += ViETest::TestError(ViE.LastError()
                                         == kViECaptureDeviceDoesnNotExist,
                                         "ERROR: %s at line %d", __FUNCTION__,
                                         __LINE__);

    // Connect the capture device to the channel
    error = ViE.capture->ConnectCaptureDevice(captureId,
                                                    channel.videoChannel);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Connect the channel again
    error = ViE.capture->ConnectCaptureDevice(captureId,
                                                    channel.videoChannel);
    numberOfErrors += ViETest::TestError(error == -1, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);
    numberOfErrors += ViETest::TestError(ViE.LastError()
        == kViECaptureDeviceAlreadyConnected, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Start the capture device
    error = ViE.capture->StartCapture(captureId);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Release invalid capture device.
    error = ViE.capture->ReleaseCaptureDevice(captureId + 1);
    numberOfErrors += ViETest::TestError(error == -1, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);
    numberOfErrors += ViETest::TestError(ViE.LastError()
        == kViECaptureDeviceDoesnNotExist, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Release the capture device
    error = ViE.capture->ReleaseCaptureDevice(captureId);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Release the capture device again
    error = ViE.capture->ReleaseCaptureDevice(captureId);
    numberOfErrors += ViETest::TestError(error == -1, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);
    numberOfErrors += ViETest::TestError(ViE.LastError()
        == kViECaptureDeviceDoesnNotExist, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Test GetOrientation
    webrtc::VideoCaptureRotation orientation;
    WebRtc_UWord8 dummy_name[5];
    error = devInfo->GetOrientation(dummy_name, orientation);
    numberOfErrors += ViETest::TestError(error == -1, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    //Test SetRotation
    error = ViE.capture->SetRotateCapturedFrames(
        captureId, webrtc::RotateCapturedFrame_90);
    numberOfErrors += ViETest::TestError(error == -1, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);
    numberOfErrors += ViETest::TestError(
        ViE.LastError() == kViECaptureDeviceDoesnNotExist,
        "ERROR: %s at line %d", __FUNCTION__, __LINE__);

    // Allocate capture device
    error = ViE.capture->AllocateCaptureDevice(*vcpm, captureId);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    error = ViE.capture->SetRotateCapturedFrames(
        captureId, webrtc::RotateCapturedFrame_0);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    error = ViE.capture->SetRotateCapturedFrames(
        captureId, webrtc::RotateCapturedFrame_90);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    error = ViE.capture->SetRotateCapturedFrames(
        captureId, webrtc::RotateCapturedFrame_180);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    error = ViE.capture->SetRotateCapturedFrames(
        captureId, webrtc::RotateCapturedFrame_270);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Release the capture device
    error = ViE.capture->ReleaseCaptureDevice(captureId);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    delete devInfo;
    vcpm->Release();

    //***************************************************************
    //	Testing finished. Tear down Video Engine
    //***************************************************************


    if (numberOfErrors > 0)
    {
        // Test failed
        ViETest::Log(" ");
        ViETest::Log(" ERROR WebRTCViECapture API Test FAILED!");
        ViETest::Log(" Number of errors: %d", numberOfErrors);
        ViETest::Log("========================================");
        ViETest::Log(" ");
        return numberOfErrors;
    }

    ViETest::Log(" ");
    ViETest::Log(" WebRTCViECapture API Test PASSED!");
    ViETest::Log("========================================");
    ViETest::Log(" ");

    return numberOfErrors;
}

int ViEAutoTest::ViECaptureExternalCaptureTest()
{
    int numberOfErrors = 0;
    ViETest::Log(" ");
    ViETest::Log("========================================");
    ViETest::Log(" WebRTCViECapture External Capture Test\n");

    //***************************************************************
    //	Begin create/initialize WebRTC Video Engine for testing
    //***************************************************************


    int error = 0;
    TbInterfaces ViE("ViECaptureExternalCaptureTest", numberOfErrors);
    tbVideoChannel channel(ViE, numberOfErrors);
    channel.StartReceive();
    channel.StartSend();

    webrtc::VideoCaptureExternal* externalCapture;
    int captureId = 0;

    // Allocate the external capture device
    webrtc::VideoCaptureModule* vcpm =
        webrtc::VideoCaptureFactory::Create(
            0, externalCapture);
    vcpm->AddRef();
    numberOfErrors += ViETest::TestError(vcpm != NULL, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    error = ViE.capture->AllocateCaptureDevice(*vcpm, captureId);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);
    numberOfErrors += ViETest::TestError(externalCapture != 0,
                                         "ERROR: %s at line %d", __FUNCTION__,
                                         __LINE__);

    // Connect the capture device to the channel
    error = ViE.capture->ConnectCaptureDevice(captureId,
                                                    channel.videoChannel);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Render the local capture
    error = ViE.render->AddRenderer(captureId, _window1, 1, 0.0, 0.0,
                                    1.0, 1.0);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Render the remote capture
    error = ViE.render->AddRenderer(channel.videoChannel, _window2, 1,
                                    0.0, 0.0, 1.0, 1.0);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    error = ViE.render->StartRender(captureId);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    error = ViE.render->StartRender(channel.videoChannel);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Register observer
    CaptureObserver observer;
    error = ViE.capture->RegisterObserver(captureId, observer);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Enable brighness alarm
    error = ViE.capture->EnableBrightnessAlarm(captureId, true);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    CaptureEffectFilter effectFilter(176, 144, numberOfErrors);
    error = ViE.image_process->RegisterCaptureEffectFilter(captureId,
                                                                effectFilter);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Call started

    ViETest::Log("You should see local preview from external capture\n"
                 "in window 1 and the remote video in window 2.\n");

    //***************************************************************
    //	Engine ready. Begin testing class
    //***************************************************************

    const unsigned int videoFrameLength = (176 * 144 * 3) / 2;
    unsigned char* videoFrame = new unsigned char[videoFrameLength];
    memset(videoFrame, 128, 176 * 144);

    // TODO: Find a file to use for testing.
    // FILE* foreman = OpenTestFile("akiyo_qcif.yuv");
    // if (foreman == NULL)
    // {
    //     ViETest::Log("Failed to open file akiyo_qcif.yuv");
    // }

    int frameCount = 0;
    webrtc::VideoCaptureCapability capability;
    capability.width = 176;
    capability.height = 144;
    capability.rawType = webrtc::kVideoI420;

    ViETest::Log("Testing external capturing and frame rate callbacks.");
    // TODO: Change when using a real file!
    // while (fread(videoFrame, videoFrameLength, 1, foreman) == 1)
    while (frameCount < 120)
    {

        externalCapture->IncomingFrame(
            videoFrame, videoFrameLength, capability,
            webrtc::TickTime::Now().MillisecondTimestamp());
        AutoTestSleep(33);

        if (effectFilter._numberOfCapturedFrames > 2)
        {
            // make sure brigthness or no picture alarm has not been triggered
            numberOfErrors += ViETest::TestError(
                observer._brightness == webrtc::Normal, "ERROR: %s at line %d",
                __FUNCTION__, __LINE__);
            numberOfErrors += ViETest::TestError(
                observer._alarm == webrtc::AlarmCleared, "ERROR: %s at line %d",
                __FUNCTION__, __LINE__);
        }
        frameCount++;
    }

    // Test brightness alarm
    // Test bright image
    for (int i = 0; i < 176 * 144; ++i)
    {
        if (videoFrame[i] <= 155)
            videoFrame[i] = videoFrame[i] + 100;
        else
            videoFrame[i] = 255;
    }
    ViETest::Log("Testing Brighness alarm");
    for (int frame = 0; frame < 30; ++frame)
    {
        externalCapture->IncomingFrame(
            videoFrame, videoFrameLength, capability,
            webrtc::TickTime::Now().MillisecondTimestamp());
        AutoTestSleep(33);
    }
    numberOfErrors += ViETest::TestError(observer._brightness == webrtc::Bright,
                                         "ERROR: %s at line %d", __FUNCTION__,
                                         __LINE__);

    // Test Dark image
    for (int i = 0; i < 176 * 144; ++i)
    {
        videoFrame[i] = videoFrame[i] > 200 ? videoFrame[i] - 200 : 0;
    }
    for (int frame = 0; frame < 30; ++frame)
    {
        externalCapture->IncomingFrame(
            videoFrame, videoFrameLength, capability,
            webrtc::TickTime::Now().MillisecondTimestamp());
        AutoTestSleep(33);
    }
    numberOfErrors += ViETest::TestError(observer._brightness == webrtc::Dark,
                                         "ERROR: %s at line %d", __FUNCTION__,
                                         __LINE__);

    // Test that frames were played
    numberOfErrors += ViETest::TestError(
        effectFilter._numberOfCapturedFrames > 150,
        "ERROR: %s at line %d", __FUNCTION__, __LINE__);

    //  Test frame rate callback
    numberOfErrors += ViETest::TestError(observer._frameRate >= 29
                                         && observer._frameRate <= 30,
                                         "ERROR: %s at line %d", __FUNCTION__,
                                         __LINE__);

    // Test no picture alarm
    ViETest::Log("Testing NoPictureAlarm.");
    AutoTestSleep(1050);
    numberOfErrors += ViETest::TestError(observer._alarm == webrtc::AlarmRaised,
                                         "ERROR: %s at line %d", __FUNCTION__,
                                         __LINE__);
    for (int frame = 0; frame < 10; ++frame)
    {
        externalCapture->IncomingFrame(
            videoFrame, videoFrameLength, capability,
            webrtc::TickTime::Now().MillisecondTimestamp());
        AutoTestSleep(33);
    }
    numberOfErrors += ViETest::TestError(
        observer._alarm == webrtc::AlarmCleared, "ERROR: %s at line %d",
        __FUNCTION__, __LINE__);

    delete videoFrame;

    // Release the capture device
    error = ViE.capture->ReleaseCaptureDevice(captureId);
    numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);

    // Release the capture device again
    error = ViE.capture->ReleaseCaptureDevice(captureId);
    numberOfErrors += ViETest::TestError(error == -1, "ERROR: %s at line %d",
                                         __FUNCTION__, __LINE__);
    numberOfErrors += ViETest::TestError(
        ViE.LastError() == kViECaptureDeviceDoesnNotExist,
        "ERROR: %s at line %d", __FUNCTION__, __LINE__);
    vcpm->Release();

    //***************************************************************
    //	Testing finished. Tear down Video Engine
    //***************************************************************

    if (numberOfErrors > 0)
    {
        // Test failed
        ViETest::Log(" ");
        ViETest::Log(" ERROR WebRTCViECapture External Capture Test FAILED!");
        ViETest::Log(" Number of errors: %d", numberOfErrors);
        ViETest::Log("========================================");
        ViETest::Log(" ");
        return numberOfErrors;
    }

    ViETest::Log(" ");
    ViETest::Log(" WebRTCViECapture External Capture Test PASSED!");
    ViETest::Log("========================================");
    ViETest::Log(" ");

    return numberOfErrors;
}
