Einführung in das IMA DAI SDK

Mit IMA SDKs können Sie Multimedia-Anzeigen ganz einfach in Ihre Websites und Apps einbinden. IMA SDKs können Anzeigen von beliebigen <ph type="x-smartling-placeholder"></ph> VAST-kompatiblen Ad-Server bereitstellen und die Anzeigenwiedergabe in Ihren Apps verwalten. Mit IMA SDKs für die dynamische Anzeigenbereitstellung Streamanfrage für Anzeigen- und Contentvideo (VOD- oder Livecontent) Das SDK gibt dann kombinierten Videostream, sodass Sie nicht zwischen Anzeige und Contentvideo wechseln müssen. in Ihrer App.

Gewünschte Lösung für die dynamische Anzeigenbereitstellung auswählen

<ph type="x-smartling-placeholder"></ph>

In dieser Anleitung wird gezeigt, wie Sie einen Live- oder VOD-Stream für die Pod-Auslieferung mit dynamischer Anzeigenbereitstellung wiedergeben. IMA DAI SDK für Roku.

Pod-Auslieferung mit der dynamischen Anzeigenbereitstellung von IMA – Übersicht

Die Implementierung der Pod-Auslieferung mit der dynamischen Anzeigenbereitstellung von IMA erfolgt in zwei SDK-Hauptkomponenten: die in diesem Leitfaden erläutert werden:

  • StreamRequest.createPodLiveStreamRequest() / StreamRequest.createPodVodStreamRequest(): Erstellt ein Objekt, das eine Streamanfrage an die Werbekampagne von Google definiert Server. Diese Anfragen geben einen Netzwerkcode und Pod-Live an ima.StreamRequest erfordert außerdem einen benutzerdefinierten Asset-Schlüssel und einen optionalen API-Schlüssel:
  • StreamManager: Ein Objekt, das die Kommunikation zwischen dem Videostream und dem IMA DAI SDK steuert, z. B. das Auslösen von Tracking-Pings und das Weiterleiten von Streamereignissen an den Publisher.

Außerdem müssen Sie die Manifestbearbeitung anfordern. Server, um den Stream abzurufen Manifest für Ihre App angezeigt. Der genaue Ablauf kann bei der Videotechnologie Partner (VTP) an VTP.

Vorbereitung

Spielen Sie Ihr Video ab.

Das Beispielvideo Spieler wird standardmäßig ein Inhaltsvideo wiedergegeben. Stellen Sie den Beispielplayer auf Ihrem Roku-Gerät an, um sicherzustellen, dass Ihre Entwicklungsumgebung richtig eingerichtet ist.

Videoplayer in einen Stream-Player für die dynamische Anzeigenbereitstellung umwandeln

Führe die folgenden Schritte aus, um einen Stream-Player zu implementieren.

sdk.xml erstellen

Fügen Sie Ihrem Projekt zusammen mit MainScene.xml eine neue Datei namens Sdk.xml hinzu. fügen Sie folgenden Textbaustein hinzu:

Sdk.xml

<?xml version = "1.0" encoding = "utf-8" ?>

  <component name = "imasdk" extends = "Task">
  <interface>
  </interface>
  <script type = "text/brightscript">
  <![CDATA[
    ' Your code goes here.
  ]]>
  </script>
  </component>

Du musst diese beiden Dateien (MainScene.xml und Sdk.xml) durchgehend bearbeiten. dieses Leitfadens.

IMA DAI SDK-Framework laden

Fügen Sie zum Laden des Frameworks zu manifest und Sdk.xml Folgendes hinzu:

Manifest

bs_libs_required=googleima3

Sdk.xml

<?xml version = "1.0" encoding = "utf-8" ?>

  <component name = "imasdk" extends = "Task">
  <interface>
  </interface>
  <script type = "text/brightscript">
  <![CDATA[
  Library "IMA3.brs"
  ]]>
  </script>
  </component>

IMA DAI SDK initialisieren

Der erste Schritt zum Laden Ihres IMA-Streams für die dynamische Anzeigenbereitstellung das IMA DAI SDK initialisieren. So wird das Script des IMA DAI SDK initialisiert.

Sdk.xml

<?xml version="1.0" encoding="utf-8" ?>

  <component name="IMASDKTask" extends="Task">
  <interface>
    <field id="IMASDKInitialized" type="Boolean" />
    <field id="errors" type="stringarray" />
  </interface>
  <script type = "text/brightscript">
  <![CDATA[
    Library "IMA3.brs"
    sub init()
      m.top.functionName = "runThread"
    end sub

    sub runThread()
      if not m.top.IMASDKInitialized
        initializeIMASDK()
      end if
    end sub

    sub initializeIMASDK()
        if m.sdk = invalid
          m.sdk = New_IMASDK()
        end if
        m.top.IMASDKInitialized = true
    end sub
  ]]>
  </script>
  </component>

Starten Sie diese Aufgabe jetzt in MainScene.xml und entfernen Sie den Aufruf zum Laden des Inhalts. .

MainScene.xml

<?xml version="1.0" encoding="utf-8" ?>

<component extends="Scene" initialFocus="myVideo" name="MainScene">
  <script type="text/brightscript">
  <![CDATA[
  function init()
    m.video = m.top.findNode("myVideo")
    m.video.notificationinterval = 1
    runIMASDKTask()
  end function

  function runIMASDKTask()
    m.IMASDKTask = createObject("roSGNode", "IMASDKTask")
    m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
    m.IMASDKTask.observeField("errors", "handleIMASDKErrors")

    m.IMASDKTask.control = "RUN"
  end function

  sub handleIMASDKInitialized()

    ' Follow your manifest manipulator (VTP) documentation to register a user
    ' streaming session if needed.

  end sub

  sub handleIMASDKErrors(message as object)
    print "------ IMA DAI SDK failed  ------"
    if message <> invalid and message.getData() <> invalid
      print "IMA DAI SDK Error ";message.getData()
    end if
  end sub
  ]]>
  </script>
  <children>
    <Video height="720" id="myVideo" visible="false" width="1280"/>
  </children>
</component>

IMA-Stream-Player erstellen

Als Nächstes müssen Sie Ihren vorhandenen roVideoScreen verwenden, um einen IMA-Stream zu erstellen. Player.

Pod-Auslieferung im Livestream

Bei Livestreams implementiert dieser Stream-Player drei Callback-Methoden: streamInitialized, adBreakStarted und adBreakEnded.

Auch die Trickwiedergabe beim Laden des Streams deaktivieren Dadurch wird verhindert, dass Nutzer Überspringen einer Pre-Roll-Anzeige unmittelbar vor Beginn der Werbeunterbrechung ausgelöst wird.

Sdk.xml

<?xml version="1.0" encoding="utf-8" ?>

  <component name="IMASDKTask" extends="Task">
  <interface>
    <field id="IMASDKInitialized" type="Boolean" />
    <field id="errors" type="stringarray" />
    <field id="urlData" type="assocarray" />
    <field id="adPlaying" type="Boolean" />
    <field id="videoNode" type="Node" />
  </interface>

  <script type="text/brightscript">
  ...
  sub runThread()
    if not m.top.IMASDKInitialized
      initializeIMASDK()
    end if

    setupPlayerCallbacks()
  end sub
  ...
  sub initializeIMASDK()
    if m.ima = invalid
      ima = New_IMASDK()
      ima.initSdk()
      m.ima = ima
    end if
    m.top.IMASDKInitialized = true
  end sub

  sub setupPlayerCallbacks()
    m.player = m.ima.createPlayer()
    m.player.top = m.top

    m.player.streamInitialized = function(urlData)
      m.top.videoNode.enableTrickPlay = false
      m.top.urlData = urlData
    end function

    m.player.adBreakStarted = function(adBreakInfo)
      print "------ Ad break started ------"
      m.top.adPlaying = true
      m.top.videoNode.enableTrickPlay = false
    end function

    m.player.adBreakEnded = function(adBreakInfo)
      print "------ Ad break ended ------"
      m.top.adPlaying = false
      m.top.videoNode.enableTrickPlay = true
    end function

  end sub
  </script>
...
</component>

Pod-Auslieferung von VOD-Streams

Für VOD-Streams implementiert dieser Stream-Player vier Callback-Methoden: streamInitialized, loadUrl, adBreakStarted und adBreakEnded. Im streamInitialized-Rückruf, bitte ruf an StreamManager.loadThirdPartyStream(). Andernfalls wird das SDK die Funktion loadUrl nicht auslöst.

In diesem Schritt fordern Sie auch eine Stream-URL von Ihrem Videotechnologiepartner an. (VTP) mit einer in loadAdPodStream() abgerufenen Stream-ID. Rufen Sie dann StreamManager.loadThirdPartyStream() durch das Manifest des Anzeigen-Pods und alle die von deinem VTP zurückgegeben wurden.

Auch die Trickwiedergabe beim Laden des Streams deaktivieren Dadurch wird verhindert, dass Nutzer Überspringen einer Pre-Roll-Anzeige unmittelbar vor Beginn der Werbeunterbrechung ausgelöst wird.

Sdk.xml

<?xml version="1.0" encoding="utf-8" ?>

  <component name="IMASDKTask" extends="Task">
  <interface>
    <field id="IMASDKInitialized" type="Boolean" />
    <field id="errors" type="stringarray" />
    <field id="adStitchedStreamInfo" type="assocarray" />
    <field id="adPlaying" type="Boolean" />
    <field id="videoNode" type="Node" />
    <field id="streamParameters" type="assocarray" />
  </interface>

  <script type="text/brightscript">
  ...
  sub runThread()
    if not m.top.IMASDKInitialized
      initializeIMASDK()
    end if

    setupPlayerCallbacks()
  end sub
  ...
  sub initializeIMASDK()
    if m.ima = invalid
      ima = New_IMASDK()
      ima.initSdk()
      m.ima = ima
    end if
    m.top.IMASDKInitialized = true
  end sub

  sub loadThirdPartyStream(adStitchedManifest as string, subtitleConfig as dynamic)
    m.streamManager.loadThirdPartyStream(adStitchedManifest, subtitleConfig)
  end sub

  sub setupPlayerCallbacks()
    m.player = m.ima.createPlayer()
    m.player.top = m.top

    m.player.streamInitialized = function(urlData)
      adStitchedManifest = m.top.streamParameters.VTPManifest.replace("[[STREAMID]]", urlData.streamId)
      loadThirdPartyStream(adStitchedManifest, m.top.streamParameters.subtitleConfig)
    end function

    m.player.loadUrl = function(streamInfo)
      m.top.adStitchedStreamInfo = streamInfo
    end function

    m.player.adBreakStarted = function(adBreakInfo)
      print "------ Ad break started ------"
      m.top.adPlaying = true
      m.top.videoNode.enableTrickPlay = false
    end function

    m.player.adBreakEnded = function(adBreakInfo)
      print "------ Ad break ended ------"
      m.top.adPlaying = false
      m.top.videoNode.enableTrickPlay = true
    end function

  end sub
  </script>
...
</component>

Anfrage für einen Live- oder VOD-Pod zur Auslieferung über einen Stream erstellen und ausführen

Sobald Sie einen Stream-Player haben, können Sie eine Streamanfrage erstellen und ausführen. In diesem Beispiel sind Daten für einen Pod-Bereitstellungsstream gespeichert in m.testPodServingStream

Pod-Auslieferung im Livestream

Speichern Sie im m.testPodServingStream-Objekt die Parameter, die von Google Ads Der Administrator muss den betreffenden Stream identifizieren, z. B. einen Netzwerkcode und benutzerdefinierten Assetschlüssel Speichern Sie auch die Manifest-URL, die für den Zugriff auf das Manifest verwendet wurde. Manipulationsserver. In diesem Fall muss die Manifest-URL den Link Die Stream-ID wird hinzugefügt, nachdem die Streamanfrage zurückgegeben wurde.

Damit AdUI wie z. B. Datenschutzinfo-Symbole unterstützt werden kann, müssen Sie außerdem eine Verweis auf den Knoten, der dein Inhaltsvideo als Teil deiner Anfrage enthält.

MainScene.xml

function init()
  m.video = m.top.findNode("myVideo")
  m.video.notificationinterval = 1
  m.testPodServingStream = {
    title: "Test live stream for DAI Pod Serving",
    assetKey: "test-live-stream",
    networkCode: "your-network-code",
    manifest: "https://.../master.m3u8?stream_id=[[STREAMID]]",
    apiKey: ""
  }
  runIMASDKTask()
end function

function runIMASDKTask()
  m.IMASDKTask = createObject("roSGNode", "IMASDKTask")

  m.IMASDKTask.streamParameters = m.testPodservingStream
  m.IMASDKTask.videoNode = m.video

  m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
  m.IMASDKTask.observeField("errors", "handleIMASDKErrors")

  m.IMASDKTask.control = "RUN"
end function

Sdk.xml

<interface>
  <field id="IMASDKInitialized" type="Boolean" />
  <field id="errors" type="stringarray" />
  <field id="urlData" type="assocarray" />
  <field id="adPlaying" type="Boolean" />
  <field id="videoNode" type="Node" />
  <field id="streamParameters" type="assocarray" />
</interface>

...

sub runThread()
  if not m.top.IMASDKInitialized
    initializeIMASDK()
  end if

  setupPlayerCallbacks()
  loadAdPodStream()
end sub

sub loadAdPodStream()
  request = m.ima.CreatePodLiveStreamRequest(m.top.streamParameters.assetKey, m.top.streamParameters.networkCode, m.top.streamParameters.apiKey)

  ' Set the player object so that the request can trigger the player's
  ' callbacks at stream initialization or playback events.
  request.player = m.player

  ' Set the video node for the IMA DAI SDK to create ad UI as its child nodes.
  request.adUiNode = m.top.video

  requestResult = m.ima.requestStream(request)
  if requestResult <> invalid
    print "Error requesting stream ";requestResult
    return
  end if

  m.streamManager = invalid
  while m.streamManager = invalid
    sleep(50)
    m.streamManager = m.ima.getStreamManager()
  end while

  if m.streamManager = invalid
    errors = CreateObject("roArray", 1, True)
    invalidStreamManagerError = "Invalid stream manager"
    print invalidStreamManagerError
    errors.push(invalidStreamManagerError)
    m.top.errors = errors
    return
  end if

  if m.streamManager["type"] <> invalid and m.streamManager["type"] = "error"
    errors = CreateObject("roArray", 1, True)
    print "Stream request returns an error. " ; m.streamManager["info"]
    errors.push(m.streamManager["info"])
    m.top.errors = errors
    return
  end if

  setupStreamManager()
  m.streamManager.start()
end sub

Pod-Auslieferung von VOD-Streams

Im m.testPodServingStream-Objekt speichern Sie den Netzwerkcode, der in der Streamanfrage, damit Google Ad Manager eine Stream-ID bereitstellen kann. Auch speichern Die Manifest-URL, die für den Zugriff auf das nutzerspezifische Manifest in Ihrem Manifest verwendet wird Manipulationsserver.

Damit AdUI wie z. B. Datenschutzinfo-Symbole unterstützt werden kann, müssen Sie auch einen Verweis auf die Knoten, der Ihr Inhaltsvideo als Teil Ihrer Anfrage enthält.

MainScene.xml

sub init()
  m.video = m.top.findNode("myVideo")
  m.video.notificationinterval = 1
  m.testPodServingStream = {
    title: "Pod Serving VOD Stream",
    networkCode: "your-network-code",
    VTPManifest: "https://.../manifest.m3u8?gam-stream-id=[[STREAMID]]",
    subtitleConfig: []
  }
  runIMASDKTask()
end sub

sub runIMASDKTask()
  m.IMASDKTask = createObject("roSGNode", "IMASDKTask")

  m.IMASDKTask.streamParameters = m.testPodservingStream
  m.IMASDKTask.videoNode = m.video

  m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
  m.IMASDKTask.observeField("errors", "handleIMASDKErrors")

  m.IMASDKTask.control = "RUN"
end sub

Sdk.xml

sub runThread()
  if not m.top.IMASDKInitialized
    initializeIMASDK()
  end if

  setupPlayerCallbacks()
  loadAdPodStream()
end sub

sub loadAdPodStream()
  request = m.ima.CreatePodVodStreamRequest(m.top.streamParameters.networkCode)

  ' Set the player object so that the request can trigger the player
  ' callbacks at stream initialization or playback events.
  request.player = m.player

  ' Set the video node for the IMA DAI SDK to create ad UI as its child nodes.
  request.adUiNode = m.top.video

  requestResult = m.ima.requestStream(request)
  if requestResult <> invalid
    print "Error requesting stream ";requestResult
    return
  end if

  m.streamManager = invalid
  while m.streamManager = invalid
    sleep(50)
    m.streamManager = m.ima.getStreamManager()
  end while

  if m.streamManager = invalid
    errors = CreateObject("roArray", 1, True)
    invalidStreamManagerError = "Invalid stream manager"
    print invalidStreamManagerError
    errors.push(invalidStreamManagerError)
    m.top.errors = errors
    return
  end if

  if m.streamManager["type"] <> invalid and m.streamManager["type"] = "error"
    errors = CreateObject("roArray", 1, True)
    print "Stream request returns an error. " ; m.streamManager["info"]
    errors.push(m.streamManager["info"])
    m.top.errors = errors
    return
  end if

  setupStreamManager()
  m.streamManager.start()
end sub

Event-Listener hinzufügen und Stream starten

Pod-Auslieferung im Livestream

Nachdem Sie Ihren Stream angefordert haben, müssen Sie nur noch ein paar Schritte ausführen: Fügen Sie Event-Listener verwenden, um den Anzeigenfortschritt zu verfolgen und Roku-Nachrichten an das SDK weiterzuleiten. Es ist wichtig, dass Sie alle Nachrichten an das SDK weiterleiten, damit die korrekte Anzeige Wiedergabe starten. Andernfalls werden die Anzeigenaufrufe falsch erfasst.

In diesem Schritt fügen Sie auch eine Funktion hinzu, um das Makro [[STREAMID]] durch die Stream-ID und übergib die ausgefüllte Manifest-Anfrage-URL an den Videoplayer. Diese Implementierung ruft die Stream-ID in diesem Schritt ab, aber abhängig von Ihrem VTP kann er bereits vor diesem Schritt verfügbar sein.

MainScene.xml

function runIMASDKTask()
  m.IMASDKTask = createObject("roSGNode", "IMASDKTask")

  m.IMASDKTask.streamParameters = m.testPodservingStream
  m.IMASDKTask.videoNode = m.video

  m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
  m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
  m.sdkTask.observeField("adStitchedStreamInfo", "loadAdStitchedStream")

  m.sdkTask.control = "RUN"
end function

sub loadAdStitchedStream(message as object)
  print "Ad pod stream information ";message
  adPodStreamInfo = message.getData()
  manifest = m.testPodservingStream.manifest.Replace("[[STREAMID]]", adPodStreamInfo.streamId)
  playStream(manifest, adPodStreamInfo.format)
end sub

sub playStream(url as string, format as string)
  vidContent = createObject("RoSGNode", "ContentNode")
  vidContent.url = url
  vidContent.title = m.testPodservingStream.title
  vidContent.streamformat = format
  m.video.content = vidContent
  m.video.setFocus(true)
  m.video.visible = true
  m.video.control = "play"
  m.video.EnableCookies()
end sub

Sdk.xml

sub runThread()
  if not m.top.IMASDKInitialized
    initializeIMASDK()
  end if

  setupPlayerCallbacks()
  loadAdPodStream()
  if m.streamManager <> invalid
    runLoop()
  end if
end sub

sub runLoop()
  m.top.videoNode.timedMetaDataSelectionKeys = ["*"]

  ' IMPORTANT: Failure to listen to the position and timedmetadata fields
  ' could result in ad impressions not being reported.
  m.port = CreateObject("roMessagePort")
  m.top.videoNode.observeField("position", m.port)
  m.top.videoNode.observeField("timedMetaData", m.port)
  m.top.videoNode.observeField("timedMetaData2", m.port)
  m.top.videoNode.observeField("state", m.port)

  while True
    msg = wait(1000, m.port)
    if m.top.videoNode = invalid
      print "exiting"
      exit while
    end if

    m.streamManager.onMessage(msg)
    currentTime = m.top.videoNode.position
    if currentTime > 3 And not m.top.adPlaying
      m.top.videoNode.enableTrickPlay = true
    end if
  end while
end sub

sub setupStreamManager()
  m.streamManager.addEventListener(m.sdk.AdEvent.ERROR, errorCallback)
  m.streamManager.addEventListener(m.sdk.AdEvent.START, startCallback)
  m.streamManager.addEventListener(m.sdk.AdEvent.FIRST_QUARTILE, firstQuartileCallback)
  m.streamManager.addEventListener(m.sdk.AdEvent.MIDPOINT, midpointCallback)
  m.streamManager.addEventListener(m.sdk.AdEvent.THIRD_QUARTILE, thirdQuartileCallback)
  m.streamManager.addEventListener(m.sdk.AdEvent.COMPLETE, completeCallback)
end sub

sub startCallback(ad as object)
  print "Callback from SDK -- Start called - "
end sub

sub firstQuartileCallback(ad as object)
  print "Callback from SDK -- First quartile called - "
end sub

sub midpointCallback(ad as object)
  print "Callback from SDK -- Midpoint called - "
end sub

sub thirdQuartileCallback(ad as object)
  print "Callback from SDK -- Third quartile called - "
end sub

sub completeCallback(ad as object)
  print "Callback from SDK -- Complete called - "
end sub

function errorCallback(error as object)
  print "Callback from SDK -- Error called - " ; error
  m.errorState = True
end function

Pod-Auslieferung von VOD-Streams

Nachdem Sie Ihren Stream angefordert haben, müssen Sie nur noch ein paar Schritte ausführen: Fügen Sie Event-Listener verwenden, um den Anzeigenfortschritt zu verfolgen und Roku-Nachrichten an das SDK weiterzuleiten. Es sollten Sie alle Nachrichten an das SDK weiterleiten, um sicherzustellen, Wiedergabe starten. Andernfalls werden die Anzeigenaufrufe falsch erfasst.

MainScene.xml

sub runIMASDKTask()
  m.IMASDKTask = createObject("roSGNode", "IMASDKTask")

  m.IMASDKTask.streamParameters = m.testPodservingStream
  m.IMASDKTask.videoNode = m.video

  m.IMASDKTask.observeField("IMASDKInitialized", "handleIMASDKInitialized")
  m.IMASDKTask.observeField("errors", "handleIMASDKErrors")
  m.sdkTask.observeField("adStitchedStreamInfo", "loadAdStitchedStream")

  m.sdkTask.control = "RUN"
end sub

sub loadAdStitchedStream(message as object)
  print "Ad pod stream information ";message
  adPodStreamInfo = message.getData()
end sub

sub playStream(url as string, format as string, subtitleConfig as object)
  vidContent = createObject("RoSGNode", "ContentNode")
  vidContent.title = m.testPodservingStream.title
  vidContent.url = url
  vidContent.subtitleConfig = subtitleConfig
  vidContent.streamformat = format
  m.video.content = vidContent
  m.video.setFocus(true)
  m.video.visible = true
  m.video.control = "play"
  m.video.EnableCookies()
end sub

Sdk.xml

sub runThread()
  if not m.top.IMASDKInitialized
    initializeIMASDK()
  end if

  setupPlayerCallbacks()
  loadAdPodStream()
  if m.streamManager <> invalid
    runLoop()
  end if
end sub

sub runLoop()
  m.top.videoNode.timedMetaDataSelectionKeys = ["*"]

  ' IMPORTANT: Failure to listen to the position and timedmetadata fields
  ' could result in ad impressions not being reported.
  m.port = CreateObject("roMessagePort")
  m.top.videoNode.observeField("position", m.port)
  m.top.videoNode.observeField("timedMetaData", m.port)
  m.top.videoNode.observeField("timedMetaData2", m.port)
  m.top.videoNode.observeField("state", m.port)

  while True
    msg = wait(1000, m.port)
    if m.top.videoNode = invalid
      exit while
    end if

    m.streamManager.onMessage(msg)
    currentTime = m.top.videoNode.position
    if currentTime > 3 and not m.top.adPlaying
      m.top.videoNode.enableTrickPlay = true
    end if
  end while
end sub

sub setupStreamManager()
  m.streamManager.addEventListener(m.sdk.AdEvent.ERROR, errorCallback)
  m.streamManager.addEventListener(m.sdk.AdEvent.START, startCallback)
  m.streamManager.addEventListener(m.sdk.AdEvent.FIRST_QUARTILE, firstQuartileCallback)
  m.streamManager.addEventListener(m.sdk.AdEvent.MIDPOINT, midpointCallback)
  m.streamManager.addEventListener(m.sdk.AdEvent.THIRD_QUARTILE, thirdQuartileCallback)
  m.streamManager.addEventListener(m.sdk.AdEvent.COMPLETE, completeCallback)
end sub

sub startCallback(ad as object)
  print "Callback from SDK -- Start called - "
end sub

sub firstQuartileCallback(ad as object)
  print "Callback from SDK -- First quartile called - "
end sub

sub midpointCallback(ad as object)
  print "Callback from SDK -- Midpoint called - "
end sub

sub thirdQuartileCallback(ad as object)
  print "Callback from SDK -- Third quartile called - "
end sub

sub completeCallback(ad as object)
  print "Callback from SDK -- Complete called - "
end sub

sub errorCallback(error as object)
  print "Callback from SDK -- Error called - " ; error
  m.errorState = True
end sub