Concurrency::task MediaFrameSourceGroup::InitializeMediaSourceWorkerAsync()

in Shared/HoloLensForCV/MediaFrameSourceGroup.cpp [115:390]


    Concurrency::task<void> MediaFrameSourceGroup::InitializeMediaSourceWorkerAsync()
    {
        return CleanupMediaCaptureAsync()
            .then([this]()
        {
            return Concurrency::create_task(
                Windows::Media::Capture::Frames::MediaFrameSourceGroup::FindAllAsync());

        }, Concurrency::task_continuation_context::get_current_winrt_context())
            .then([this](Windows::Foundation::Collections::IVectorView<Windows::Media::Capture::Frames::MediaFrameSourceGroup^>^ sourceGroups)
        {
            Windows::Media::Capture::Frames::MediaFrameSourceGroup^ selectedSourceGroup;

            for (Windows::Media::Capture::Frames::MediaFrameSourceGroup^ sourceGroup : sourceGroups)
            {
                const wchar_t* sourceGroupDisplayName =
                    sourceGroup->DisplayName->Data();

                //
                // Note: this is the display name of the media frame source group associated
                // with the photo/video camera (or, RGB camera) on HoloLens Development Edition.
                //
                const wchar_t* c_HoloLensDevelopmentEditionPhotoVideoSourceGroupDisplayName =
                    L"MN34150";

                const wchar_t* c_HoloLensResearchModeSensorStreamingGroupDisplayName =
                    L"Sensor Streaming";

                if (MediaFrameSourceGroupType::PhotoVideoCamera == _mediaFrameSourceGroupType &&
                    (0 == wcscmp(c_HoloLensDevelopmentEditionPhotoVideoSourceGroupDisplayName, sourceGroupDisplayName)))
                {
#if DBG_ENABLE_INFORMATIONAL_LOGGING
                    dbg::trace(
                        L"MediaFrameSourceGroup::InitializeMediaSourceWorkerAsync: found the photo-video media frame source group.");
#endif /* DBG_ENABLE_INFORMATIONAL_LOGGING */

                    selectedSourceGroup =
                        sourceGroup;

                    break;
                }
#if ENABLE_HOLOLENS_RESEARCH_MODE_SENSORS
                else if (MediaFrameSourceGroupType::HoloLensResearchModeSensors == _mediaFrameSourceGroupType &&
                    (0 == wcscmp(c_HoloLensResearchModeSensorStreamingGroupDisplayName, sourceGroupDisplayName)))
                {
#if DBG_ENABLE_INFORMATIONAL_LOGGING
                    dbg::trace(
                        L"MediaFrameSourceGroup::InitializeMediaSourceWorkerAsync: found the HoloLens Sensor Streaming media frame source group.");
#endif /* DBG_ENABLE_INFORMATIONAL_LOGGING */

                    selectedSourceGroup =
                        sourceGroup;

                    break;
                }
#endif /* ENABLE_HOLOLENS_RESEARCH_MODE_SENSORS */
            }

            if (nullptr == selectedSourceGroup)
            {
#if DBG_ENABLE_INFORMATIONAL_LOGGING
                dbg::trace(
                    L"MediaFrameSourceGroup::InitializeMediaSourceWorkerAsync: selected media frame source group not found.");
#endif /* DBG_ENABLE_INFORMATIONAL_LOGGING */

                return Concurrency::task_from_result();
            }

            //
            // Initialize MediaCapture with the selected group.
            //
            return TryInitializeMediaCaptureAsync(selectedSourceGroup)
                .then([this, selectedSourceGroup](bool initialized)
            {
                if (!initialized)
                {
                    return CleanupMediaCaptureAsync();
                }

                //
                // Set up frame readers, register event handlers and start streaming.
                //
                auto startedSensors =
                    std::make_shared<std::unordered_set<SensorType, SensorTypeHash>>();

                Concurrency::task<void> createReadersTask =
                    Concurrency::task_from_result();

#if DBG_ENABLE_INFORMATIONAL_LOGGING
                dbg::trace(
                    L"MediaFrameSourceGroup::InitializeMediaSourceWorkerAsync: selected group has %i media frame sources",
                    _mediaCapture->FrameSources->Size);
#endif /* DBG_ENABLE_INFORMATIONAL_LOGGING */

                for (Windows::Foundation::Collections::IKeyValuePair<Platform::String^, Windows::Media::Capture::Frames::MediaFrameSource^>^ kvp : _mediaCapture->FrameSources)
                {
                    Windows::Media::Capture::Frames::MediaFrameSource^ source =
                        kvp->Value;

                    createReadersTask = createReadersTask.then([this, startedSensors, source]()
                    {
                        SensorType sensorType =
                            GetSensorType(
                                source);

                        if (SensorType::Undefined == sensorType)
                        {
                            //
                            // We couldn't map the source to a Research Mode sensor type. Ignore this source.
                            //
#if DBG_ENABLE_INFORMATIONAL_LOGGING
                            dbg::trace(
                                L"MediaFrameSourceGroup::InitializeMediaSourceWorkerAsync: could not map the media frame source to a Research Mode sensor type!");
#endif /* DBG_ENABLE_INFORMATIONAL_LOGGING */

                            return Concurrency::task_from_result();
                        }
                        else if (startedSensors->find(sensorType) != startedSensors->end())
                        {
                            //
                            // We couldn't map the source to a Research Mode sensor type. Ignore this source.
                            //
#if DBG_ENABLE_INFORMATIONAL_LOGGING
                            dbg::trace(
                                L"MediaFrameSourceGroup::InitializeMediaSourceWorkerAsync: sensor type %s has already been initialized!",
                                sensorType.ToString());
#endif /* DBG_ENABLE_INFORMATIONAL_LOGGING */

                            return Concurrency::task_from_result();
                        }
                        else if (!IsEnabled(sensorType))
                        {
                            //
                            // The sensor type was not explicitly enabled by user. Ignore this source.
                            //
#if DBG_ENABLE_INFORMATIONAL_LOGGING
                            dbg::trace(
                                L"MediaFrameSourceGroup::InitializeMediaSourceWorkerAsync: sensor type %s has not been enabled!",
                                sensorType.ToString());
#endif /* DBG_ENABLE_INFORMATIONAL_LOGGING */

                            return Concurrency::task_from_result();
                        }

                        //
                        // Look for a format which the FrameRenderer can render.
                        //
                        Platform::String^ requestedSubtype =
                            nullptr;

                        auto found =
                            std::find_if(
                                begin(source->SupportedFormats),
                                end(source->SupportedFormats),
                                [&](Windows::Media::Capture::Frames::MediaFrameFormat^ format)
                            {
                                requestedSubtype =
                                    GetSubtypeForFrameReader(
                                        source->Info->SourceKind,
                                        format);

                                return requestedSubtype != nullptr;
                            });

                        if (requestedSubtype == nullptr)
                        {
                            //
                            // No acceptable format was found. Ignore this source.
                            //
                            return Concurrency::task_from_result();
                        }

                        //
                        // Tell the source to use the format we can render.
                        //
                        return Concurrency::create_task(
                            source->SetFormatAsync(*found))
                            .then([this, source, requestedSubtype]()
                        {
                            return Concurrency::create_task(
                                _mediaCapture->CreateFrameReaderAsync(
                                    source,
                                    requestedSubtype));

                        }, Concurrency::task_continuation_context::get_current_winrt_context())
                            .then([this, sensorType](Windows::Media::Capture::Frames::MediaFrameReader^ frameReader)
                        {
                            ISensorFrameSink^ optionalSensorFrameSink =
                                nullptr != _optionalSensorFrameSinkGroup
                                ? _optionalSensorFrameSinkGroup->GetSensorFrameSink(
                                    sensorType)
                                : nullptr;

                            MediaFrameReaderContext^ frameReaderContext =
                                ref new MediaFrameReaderContext(
                                    sensorType,
                                    _spatialPerception,
                                    optionalSensorFrameSink);

                            _frameReaders[(int32_t)sensorType] =
                                frameReaderContext;

                            Windows::Foundation::EventRegistrationToken token =
                                frameReader->FrameArrived +=
                                    ref new Windows::Foundation::TypedEventHandler<
                                        Windows::Media::Capture::Frames::MediaFrameReader^,
                                        Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^>(
                                            frameReaderContext,
                                            &MediaFrameReaderContext::FrameArrived);

                            //
                            // Keep track of created reader and event handler so it can be stopped later.
                            //
                            _frameEventRegistrations.push_back(
                                std::make_pair(
                                    frameReader,
                                    token));

#if DBG_ENABLE_INFORMATIONAL_LOGGING
                            dbg::trace(
                                L"MediaFrameSourceGroup::InitializeMediaSourceWorkerAsync: created the '%s' frame reader",
                                sensorType.ToString()->Data());
#endif /* DBG_ENABLE_INFORMATIONAL_LOGGING */

                            return Concurrency::create_task(
                                frameReader->StartAsync());

                        }, Concurrency::task_continuation_context::get_current_winrt_context())
                            .then([this, sensorType, startedSensors](Windows::Media::Capture::Frames::MediaFrameReaderStartStatus status)
                        {
                            if (status == Windows::Media::Capture::Frames::MediaFrameReaderStartStatus::Success)
                            {
#if DBG_ENABLE_INFORMATIONAL_LOGGING
                                dbg::trace(
                                    L"MediaFrameSourceGroup::InitializeMediaSourceWorkerAsync: started the '%s' frame reader",
                                    sensorType.ToString()->Data());
#endif /* DBG_ENABLE_INFORMATIONAL_LOGGING */

                                startedSensors->insert(
                                    sensorType);
                            }
                            else
                            {
#if DBG_ENABLE_ERROR_LOGGING
                                dbg::trace(
                                    L"MediaFrameSourceGroup::InitializeMediaSourceWorkerAsync: unable to start the '%s' frame reader. Error: %s",
                                    sensorType.ToString()->Data(),
                                    status.ToString()->Data());
#endif /* DBG_ENABLE_ERROR_LOGGING */
                            }

                        }, Concurrency::task_continuation_context::get_current_winrt_context());

                    }, Concurrency::task_continuation_context::get_current_winrt_context());
                }

                //
                // Run the loop and see if any sources were used.
                //
                return createReadersTask.then([this, startedSensors, selectedSourceGroup]()
                {
                    if (startedSensors->size() == 0)
                    {
#if DBG_ENABLE_INFORMATIONAL_LOGGING
                        dbg::trace(
                            L"MediaFrameSourceGroup::InitializeMediaSourceWorkerAsync: no eligible sources in '%s'",
                            selectedSourceGroup->DisplayName->Data());
#endif /* DBG_ENABLE_INFORMATIONAL_LOGGING */
                    }

                }, Concurrency::task_continuation_context::get_current_winrt_context());

            }, Concurrency::task_continuation_context::get_current_winrt_context());

        }, Concurrency::task_continuation_context::get_current_winrt_context());
    }