ARM odhalil plán budoucích CPU jader: Deimos a Hercules pro přímý útok na Intel

17. 8. 2018

Sdílet

Ilustrační obrázek Autor: loriklaszlo – Depositphotos
Ilustrační obrázek

Firma ARM letos vystupňovala svůj zatím stále hlavně papírový souboj s Intelem. Spolu s Qualcommem a Microsoftem připravuje notebooky s Windows poháněné čipy s jádry ARM, jejichž první generace s Cortexy-A73 už je venku a druhá by měla být na cestě. Při představení jádra Cortex-A76 v červnu byl přislíben výkon (nebo alespoň IPC) blízké architekturám Intelu a nyní ARM říká, že už příští rok by mohl možná dosáhnout ještě víc. Firma představila roadmapu procesorů na následující léta, což doposud nedělala, a v ní nové architektury, které mají opět přinést výrazná zlepšení výkonu.  

ARM chce každý rok zvýšit výkon o 15 %

ARM měl v posledních letech docela agresivní „kadenci“ vydávání nových architektur. Cortex-A73, Cortex-A75 a nyní A76 přicházely v ročních intervalech, což výrobcům mobilních čipů dovolovalo rychle po sobě vydávat SoCy se zvyšujícím se výkonem CPU. ARM je na to logicky patřičně hrdý a nyní prozradil, že toto tempo bude udržovat i do budoucna. Také v roce 2019 a 2020 uvede nová výkonná jádra Cortex, které mají opět rychlosti čipů ARM nakopnout. ARM s nimi totiž údajně chce nastavit či držet trend, kdy se výkon jeho CPU architektur bude každý rok zvyšovat v průměru o 15 %.

2019: Deimos

Finální označení těchto jader zatím sdělena nebyla. ARM se ale podělil o jejich interní kódová jména, která jsou u firmy tradičně odvozena od řeckých božstev a mytologických postav. Na rok 2019 (pravděpodobně opět bude odhaleno začátkem léta) připravuje ARM jádro Deimos. Deimos je následníkem Cortexu-A76 a počítá se u něj s tím, že se bude vyrábět na různých variantách 7nm procesu, pro nějž je optimalizován (A76 je vyvinuta pro 7nm, ale také i pro 10nm proces). Deimos má údajně zvýšit výpočetní výkon proti architektuře Cortex-A76 o 15 % nebo i o víc. Ačkoliv odhalení má být v roce 2019 a procesory s touto architekturou asi trh obsadí hlavně v roce dalším, ARM uvádí, že výrobci už k tomuto IP budou mít přístup od letoška, aby své SoC připravili.

2020: Hercules

V roce 2020 pak pravděpodobně s ročním odstupem vyjde další generace, která má kódové označení Hercules (jméno možná může svědčit o ambicích, vkládaných do tohoto návrhu). Hercules má „pokračovat v trajektorii zvyšování výkonu“, což asi má znamenat opět oněch 15 % výkonu navíc, ale přesné číslo zde už ARM uvést nechce. Zároveň má Hercules také vylepšit efektivitu co do spotřeby a co do spotřebovaných tranzistorů o 10 %. Je zajímavé, že u Deimosu toto jmenováno není. Teoreticky by to mohlo značit, že Deimos půjde trošku cestou hrubé síly, zatímco Hercules možná naopak cestou šikovné optimalizace, kdy se podobný výkon bude dosahovat méně prostředky (něco jako v případě rozdílných koncepcí jader Cortex-A72 a pak užšího A73). Ovšem asi je třeba dát si pozor na to, abychom pár vět zvolených marketingem nepřeanalyzovali. Toto je přece jen dost spekulativní.

Roadmapa výkonných jader ARM určených i pro notebooky a PC Roadmapa výkonných jader ARM určených i pro notebooky a PC

Hercules opět ještě počítá s výrobou na 7nm procesu. Spolu s ním ale bude optimalizován paralelně už i pro 5nm proces. Architektura bude odhalena v roce 2020, ale partneři opět dostanou IP už v roce 2019. A hotové čipy by se asi mohly objevovat během roku 2021, nejdřív asi hlavně na 7nm procesu. Nicméně se asi dá čekat, že výrobci mobilních SoC s jádry ARM v letech 2021–2022 budou přecházet na 5nm proces, když s tím ARM v návrhu architektury počítá. TSMC sice říká, že 5nm výrobu spustí zkušebně už v roce 2019, ale do komerčního nasazení to asi bude chvíli trvat.

Je třeba říct, že ony údaje o zvýšeném výkonu jsou jen prognózy a očekávání. Benchmarky dávané takto v předstihu je vždy třeba brát s rezervou, navíc je jako obvykle možné, že jde o „až“ čísla pro případy, kde nová jádra budou mít nadprůměrně vysoké přínosy, a typická zlepšení budou menší. ARM bohužel také nespecifikuje, jaká část oněch každoročních 15% zlepšení má být v architektonických změnách zlepšujících IPC a jakou roli bude hrát pouhé zvýšení frekvence díky pokročilejší výrobě.

HP Envy X2 HP Envy X2: tzv. "Always Connected PC" s ARM procesorem procesorem Snapdragon 435 a Windows 10

Cortex-A76 má být rychlejší než Skylake… v SPECInt2006

ARM tato jádra prezentuje jako architektury, které mohou pohánět procesory určené už nejen pro mobilní zařízení, ale i plnotučné notebooky a PC. V tomto kontextu jinak také zveřejnil nová výkonnostní čísla pro již odhalený Cortex-A76. Jde o test SPECint2006 kompilovaný pomocí GCC 7. V něm údajně Cortex-A76 běžící na 3 GHz a s 4MB L3 cache má dosáhnout prakticky stejný jednovláknový výkon, jako Intel Core i5-7300U, což je dvoujádro generace Kaby Lake s taktem v turbu 3,5 GHz. ARM bohužel dodal jen graf (na němž je sloupeček ARMu o pár pixelů nižší), přesná čísla nejsou. Také není úplně jasné, na jaké frekvenci přesně Kaby Lake běželo. Podle žlutého sloupečku, což je výsledek pro jeho základní takt 2,6 GHz, bych si tipl, že to nebylo plných 3,5 GHz. Podle velikosti sloupečku (což může být zavádějící) by to mohlo být okolo 3,15 GHz. Ale pokud benchmark neškáluje lineárně, tak i víc. SPECint2006 ale údajně částečně závisí na rychlosti pamětí, takže škálování  lineární být nemusí.

I tak by asi tento test ukazoval přinejmenším na docela blízké IPC, bohužel kvůli nejasné frekvenci Kaby Lake nevíme, zda IPC nemá být dokonce není vyšší. Jde ovšem o jen jeden vybraný test, který možná nemusí ukazovat úplně typický obrázek (vzpomeňte si na to, jak například jádrům Zen jde nadprůměrně dobře Cinebench, ale třeba x265 mají zase naopak nadprůměrnou výhodu Intely). Také je dost možné, že IPC jádra Cortex-A76 může pocházet i z věcí jako je nízká latence L1, které ale zase způsobí, že jeho frekvence bude mít strop hodně nízko. ARM uvádí, že čipy pro notebooky budou moci běžet na 3,0 až 3,3 GHz. Vzhledem k tomu, že Kaby Lake se dokáže dostat na 4,5 GHz i výš při OC, je jasné, že při započítání jak IPC, tak frekvence bude Intel pořád o hodně vepředu. Také je tu jeden malý detail: výkon Cortexu-A76 je odhadovaný, ne reálně naměřený.

bitcoin_smenarna

Ve SPECint2006 má údajně 3Ghz Cortex-A76 vyvíjet podobný výkon jako Intel Core i5-7300U (Kaby Lake na 2,6 až 3,5 GHz) Ve SPECint2006 má podle ARMu údajně 3Ghz Cortex-A76 vyvíjet podobný výkon jako Intel Core i5-7300U (Kaby Lake na 2,6 až 3,5 GHz)

Lepší energetická efektivita ARMu (ovšem na 7nm procesu)

ARM také uvádí, že onen uvažovaný SoC s 3GHz jádry Cortex-A76 bude mít TDP okolo 5 W, zatímco Core i5-7300U má stanoveno 15W TDP. To má být ukázka lepší energetické efektivity. Zde je ale třeba namítnout, že SPECint2006 by měla být jednovláknová zátěž, při které asi čip Intelu nespotřebovává plných 15 W (kolik bude potřebovat při 3,0 GHz jedno jádro A76, to ale také nevíme). Kromě toho je procesor Intelu 14nm, kdežto onen uvažovaný ARM je modelován s 7nm tranzistory. Test je jinak na Ubuntu 18.04.

Jak se tato nacházející jádra ARM budou schopné popasovat s jádry Intel (a potažmo AMD), to asi bude nejlepší hodnotit až na reálných čipech. Ony notebooky se systémem Windows by pro to možná mohly poskytovat dobrou příležitost. Většina x86 aplikací na nich sice běží v emulaci, ale je možné na nich spouštět i nativní binárky architektury ARMv8. Takže s vhodnou aplikací bude možné srovnávat nativní výkon jader Intel a ARM na jednom operačním systému a na podobné platformě (což je problém při benchmarkování třeba mobilů proti notebookům). Mohly by to být každopádně zajímavé časy.

Autor článku

Redaktor portálu Cnews.cz. Zaměřuje se na procesory, mobilní SoC, grafické karty, disky a další počítačový hardware. Profil autora →

'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }
'; document.getElementById('outstream-iframe').onload = function () { setupIframe(); } replayScreen = document.getElementById('iinfoOutstreamReplay'); iinfoOutstreamPosition = document.getElementById('iinfoOutstreamPosition'); outstreamContainer = document.getElementsByClassName('outstream-container')[0]; setupReplayScreen(); } function setupIframe() { outstreamDocument = document.getElementById('outstream-iframe').contentWindow.document; let el = outstreamDocument.createElement('style'); outstreamDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:-5px;right:25px}"; videoContent = outstreamDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; if ( location.href.indexOf('rejstriky.finance.cz') !== -1 || location.href.indexOf('finance-rejstrik') !== -1 || location.href.indexOf('firmy.euro.cz') !== -1 || location.href.indexOf('euro-rejstrik') !== -1 || location.href.indexOf('/rejstrik/') !== -1 || location.href.indexOf('/rejstrik-firem/') !== -1) { outstreamDirectPlayed = true; soundAllowed = true; iinfoVastUrlIndex = 0; } if (!outstreamDirectPlayed) { console.log('OUTSTREAM direct'); setUpIMA(true); } else { if (soundAllowed) { const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('OUTSTREAM sound allowed'); setUpIMA(false); }).catch(function () { console.log('OUTSTREAM sound forbidden'); renderBanner(); }); } } else { renderBanner(); } } } function getWrapper() { let articleWrapper = document.querySelector('.rs-outstream-placeholder'); // Outstream Placeholder from RedSys manipulation if (articleWrapper && articleWrapper.style.display !== 'block') { articleWrapper.innerHTML = ""; articleWrapper.style.display = 'block'; } // Don't render OutStream on homepages if (articleWrapper === null) { if (document.querySelector('body.p-index')) { return null; } } if (articleWrapper === null) { articleWrapper = document.getElementById('iinfo-outstream'); } if (articleWrapper === null) { articleWrapper = document.querySelector('.layout-main__content .detail__article p:nth-of-type(6)'); } if (articleWrapper === null) { // Euro, Autobible, Zdravi articleWrapper = document.querySelector('.o-article .o-article__text p:nth-of-type(6)'); } if (articleWrapper === null) { articleWrapper = document.getElementById('sidebar'); } if (!articleWrapper) { console.error("Outstream wrapper of article was not found."); } return articleWrapper; } function setupDimensions() { outstreamWidth = Math.min(iinfoOutstreamPosition.offsetWidth, 480); outstreamHeight = Math.min(iinfoOutstreamPosition.offsetHeight, 320); } /** * Sets up IMA ad display container, ads loader, and makes an ad request. */ function setUpIMA(direct) { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); if (direct) { adsRequest.adTagUrl = directVast; console.log('Outstream DIRECT CAMPAING advert: ' + directVast); videoContent.muted = true; videoContent.volume = 0; outstreamDirectPlayed = true; } else { adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Outstream advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; } // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = outstreamWidth; // adsRequest.linearAdSlotHeight = outstreamHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function setupReplayScreen() { replayScreen.addEventListener('click', function () { iinfoOutstreamPosition.remove(); iinfoVastUrlIndex = 0; outstreamInit(); }); } /** * Sets the 'adContainer' div as the IMA ad display container. */ function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. outstreamDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( outstreamDocument.getElementById('adContainer'), videoContent); } function unmuteAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } } /** * Loads the video content and initializes IMA ad playback. */ function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(outstreamWidth, outstreamHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } /** * Handles the ad manager loading and sets ad event listeners. * @param { !google.ima.AdsManagerLoadedEvent } adsManagerLoadedEvent */ function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } /** * Handles actions taken in response to ad events. * @param { !google.ima.AdEvent } adEvent */ function onAdEvent(adEvent) { // Retrieve the ad from the event. Some events (for example, // ALL_ADS_COMPLETED) don't have ad object associated. const ad = adEvent.getAd(); console.log('Outstream event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: // This is the first event sent for an ad - it is possible to // determine whether the ad is a video ad or an overlay. if (!ad.isLinear()) { // Position AdDisplayContainer correctly for overlay. // Use ad.width and ad.height. videoContent.play(); } outstreamDocument.getElementById('adContainer').style.width = '100%'; outstreamDocument.getElementById('adContainer').style.maxWidth = '640px'; outstreamDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); // This event indicates the ad has started - the video player // can adjust the UI, for example display a pause button and // remaining time. if (ad.isLinear()) { // For a linear ad, a timer can be started to poll for // the remaining time. intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } outstreamDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (outstreamLastError === 303) { if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } } break; case google.ima.AdEvent.Type.COMPLETE: // This event indicates the ad has finished - the video player // can perform appropriate UI actions, such as removing the timer for // remaining time detection. if (ad.isLinear()) { clearInterval(intervalTimer); } if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } break; } } /** * Handles ad errors. * @param { !google.ima.AdErrorEvent } adErrorEvent */ function onAdError(adErrorEvent) { // Handle the error logging. console.log(adErrorEvent.getError()); outstreamLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { renderBanner(); } } function renderBanner() { if (isBanner) { console.log('Outstream: Render Banner'); iinfoOutstreamPosition.innerHTML = ""; iinfoOutstreamPosition.style.height = "330px"; iinfoOutstreamPosition.appendChild(bannerDiv); } else { console.log('Outstream: Banner is not set'); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoOutstreamPosition.remove(); outstreamInit(); } else { return false; } adVolume = 1; return true; } /** * Pauses video content and sets up ad UI. */ function onContentPauseRequested() { videoContent.pause(); // This function is where you should setup UI for showing ads (for example, // display ad timer countdown, disable seeking and more.) // setupUIForAds(); } /** * Resumes video content and removes ad UI. */ function onContentResumeRequested() { videoContent.play(); // This function is where you should ensure that your UI is ready // to play content. It is the responsibility of the Publisher to // implement this function when necessary. // setupUIForContent(); } function onActiveView() { if (outstreamContainer) { const containerOffset = outstreamContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (outstreamPaused) { adsManager.resume(); outstreamPaused = false; } return true; } else { if (!outstreamPaused) { adsManager.pause(); outstreamPaused = true; } } } return false; } let outstreamInitInterval; if (typeof cpexPackage !== "undefined") { outstreamInitInterval = setInterval(tryToInitializeOutstream, 100); } else { const wrapper = getWrapper(); if (wrapper) { let outstreamInitialized = false; window.addEventListener('scroll', () => { if (!outstreamInitialized) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { outstreamInit(); outstreamInitialized = true; } } }); } } function tryToInitializeOutstream() { const wrapper = getWrapper(); if (wrapper) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { if (cpexPackage.adserver.displayed) { clearInterval(outstreamInitInterval); outstreamInit(); } } } else { clearInterval(outstreamInitInterval); } } }
OSZAR »