Source: services/HdmiService.js

    /**
     * @ngdoc service
     * @name HdmiService
     * @module s4c.services.HdmiService
     * 
     * @description  Componente para acesso a api do backend e/ou comunicação entre controllers
     * 
     *
     */
     
(function () {
    'use strict';

    angular.module('s4c.services').factory(
        'HdmiService', HdmiService);

    HdmiService.$inject = [];

   /**	
	* @method HdmiService
	*/
    function HdmiService() {

        var service = {
            attachDevice: attachDevice,
            getDevicesList: getDevicesList
        };

  		/**	
		* @method attachDevice
		* @param {*} element
		* @param {*} inputDevices
		*/
        function attachDevice(element, inputDevices) {
            bestResolutionId = 0;
            compareDevicesWithNames(inputDevices, element);
            element.setSinkId(inputDevices.audiooutput.deviceId)
                .then(function () {
                    console.log('Success, audio output device attached: ' + inputDevices.audiooutput.deviceId);
                })
                .catch(function (error) {
                    var errorMessage = error;
                    console.error(errorMessage);
                });
        }

        var bestResolutionId = 0;

  		/**	
		* @method scanResolutionVideo
		* @param {*} element
		* @param {*} inputDevices
		*/
        function scanResolutionVideo(inputDevices, element) {
            var constraints = {
                video: {
                    deviceId: { exact: inputDevices.videoinput.deviceId }
                }
            };
            constraints.video.width = { exact: quickScan[bestResolutionId].width };
            constraints.video.height = { exact: quickScan[bestResolutionId].height };
            constraints.audio = true;
            constraints.video.frameRate = { ideal: 25, max: 60 };

            navigator.mediaDevices.getUserMedia(constraints)
                .then(function (stream) {
                    play(inputDevices, constraints, element)
                })
                .catch(function (error) {
                    console.log(error);
                    bestResolutionId = ++bestResolutionId;
                    scanResolutionVideo(inputDevices, element);
                });
        }

  		/**	
		* @method play
		* @param {*} element
		* @param {*} constraints
		* @param {*} inputDevices
		*/
        function play(inputDevices, constraints, element) {
            if (inputDevices.audioinput.deviceId) {
                constraints['audio'] = {
                    deviceId: { exact: inputDevices.audioinput.deviceId },
                    channelCount: 2,
                    echoCancellation: false,
                    sampleSize: 32,
                    sampleRate: 48000
                };
            } else {
                constraints['audio'] = false;
            }

            navigator.mediaDevices.getUserMedia(constraints)
                .then(function (stream) {
                    gotStream(stream, element)
                })
                .catch(function (error) { handleError(error, inputDevices, element) });
        }

  		/**	
		* @method gotStream
		* @param {*} element
		* @param {*} stream
		*/
        function gotStream(stream, element) {
            element.poster = null;
            element.style.backgroundColor = "#000";
            element.srcObject = stream;
        }

  		/**	
		* @method handleError
		* @param {*} element
		* @param {*} error
		* @param {*} inputDevices
		*/
        function handleError(error, inputDevices, element) {
            console.log('Error: ', error);
            compareDevicesWithNames(inputDevices, element);
        }

  		/**	
		* @method compareDevicesWithNames
		* @param {*} element
		* @param {*} inputDevices
		*/
        function compareDevicesWithNames(inputDevices, element) {

            if(!inputDevices){
                return;
            }
            navigator.mediaDevices.enumerateDevices()
                .then(function (deviceInfos) {
                    for (var index in deviceInfos) {
                        var deviceId = deviceInfos[index].deviceId;
                        var label = deviceInfos[index].label;
                        var kind = deviceInfos[index].kind;
                        if (kind == 'videoinput') {
                            if (inputDevices.videoinput && inputDevices.videoinput.label == label && inputDevices.videoinput.deviceId != deviceId) {
                                inputDevices.videoinput.deviceId = deviceId;
                                inputDevices.videoinput.label = label;
                            }
                        }

                        if (kind == 'audioinput') {
                            if (inputDevices.audioinput && inputDevices.audioinput.label == label && inputDevices.audioinput.deviceId != deviceId) {
                                inputDevices.audioinput.deviceId = deviceId;
                                inputDevices.audioinput.label = label;
                            }
                        }

                        if (kind == 'audiooutput') {
                            if (inputDevices.audiooutput && inputDevices.audiooutput.label == label && inputDevices.audiooutput.deviceId != deviceId) {
                                inputDevices.audiooutput.deviceId = deviceId;
                                inputDevices.audiooutput.label = label;
                            }
                        }
                    }
                    scanResolutionVideo(inputDevices, element);
                })
                .catch(handleError);
        }

  		/**	
		* @method getDevicesList
		*/
        function getDevicesList(){
            return navigator.mediaDevices.enumerateDevices();
        }

        const quickScan = [
            {
                "label": "4K(UHD)",
                "width": 3840,
                "height": 2160,
                "ratio": "16:9"
            },
            {
                "label": "1200p",
                "width": 1920,
                "height": 1200,
                "ratio": "16:10"
            },
            {
                "label": "1080p(FHD)",
                "width": 1920,
                "height": 1080,
                "ratio": "16:9"
            },
            {
                "label": "UXGA",
                "width": 1600,
                "height": 1200,
                "ratio": "4:3"
            },
            {
                "label": "720p(HD)",
                "width": 1280,
                "height": 720,
                "ratio": "16:9"
            },
            {
                "label": "SVGA",
                "width": 800,
                "height": 600,
                "ratio": "4:3"
            },
            {
                "label": "VGA",
                "width": 640,
                "height": 480,
                "ratio": "4:3"
            },
            {
                "label": "360p(nHD)",
                "width": 640,
                "height": 360,
                "ratio": "16:9"
            },
            {
                "label": "CIF",
                "width": 352,
                "height": 288,
                "ratio": "4:3"
            },
            {
                "label": "QVGA",
                "width": 320,
                "height": 240,
                "ratio": "4:3"
            },
            {
                "label": "QCIF",
                "width": 176,
                "height": 144,
                "ratio": "4:3"
            },
            {
                "label": "QQVGA",
                "width": 160,
                "height": 120,
                "ratio": "4:3"
            }

        ];
        return service;
    }
}());