From 169029da1e41b6911657d862816d0be405575841 Mon Sep 17 00:00:00 2001 From: Constanza Dibueno Date: Mon, 17 Mar 2025 11:39:15 -0300 Subject: [PATCH 1/9] update messageData value on getEvent to match callback event on dash 6 r17 --- src/dash/DashAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dash/DashAdapter.js b/src/dash/DashAdapter.js index 9f771265e8..4aca89f548 100644 --- a/src/dash/DashAdapter.js +++ b/src/dash/DashAdapter.js @@ -496,7 +496,7 @@ function DashAdapter() { const duration = eventBox.event_duration / timescale; const id = eventBox.id; - const messageData = eventBox.message_data; + const messageData = schemeIdUri === constants.MPD_CALLBACK_SCHEME & eventBox.value ? eventBox.value : eventBox.message_data; event.eventStream = eventStream; event.eventStream.value = value; @@ -511,7 +511,7 @@ function DashAdapter() { } else { event.parsedMessageData = (messageData instanceof Uint8Array) ? utf8ArrayToStr(messageData) : null; } - + return event; } catch (e) { return null; From c16ec77d2e0466fae96906b52f10a2388715a4ff Mon Sep 17 00:00:00 2001 From: Constanza Dibueno Date: Mon, 17 Mar 2025 11:39:58 -0300 Subject: [PATCH 2/9] add dash adapter unit tests for callback event --- test/unit/test/dash/dash.DashAdapter.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/unit/test/dash/dash.DashAdapter.js b/test/unit/test/dash/dash.DashAdapter.js index 39dc732137..664e124355 100644 --- a/test/unit/test/dash/dash.DashAdapter.js +++ b/test/unit/test/dash/dash.DashAdapter.js @@ -272,6 +272,20 @@ describe('DashAdapter', function () { expect(event).to.be.an('object'); }); + it('should return an event with a valid parsedMessageData', function () { + const representation = { presentationTimeOffset: 0, adaptation: { period: { start: 0 } } }; + const messageData = new Uint8Array([10, 20, 30]); + const eventBox = { + scheme_id_uri: 'id', + value: 'value', + message_data: messageData, + } + + const event = dashAdapter.getEvent( eventBox, { 'id/value': {} }, 0, representation); + expect(event.parsedMessageData).to.be.a('string').and.not.empty; + expect(event.parsedMessageData).to.not.be.undefined; + }); + it('should calculate correct start time for a version 0 event without PTO', function () { const representation = { adaptation: { period: { start: 10 } } }; const eventBox = { scheme_id_uri: 'id', value: 'value', presentation_time_delta: 12, version: 0 }; From 36902f45a4cee0af20e8d49fdd251c44db59f2bb Mon Sep 17 00:00:00 2001 From: Constanza Dibueno Date: Mon, 17 Mar 2025 11:40:19 -0300 Subject: [PATCH 3/9] add constants --- src/streaming/constants/Constants.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/streaming/constants/Constants.js b/src/streaming/constants/Constants.js index a95bc2d6c0..6ca0568d34 100644 --- a/src/streaming/constants/Constants.js +++ b/src/streaming/constants/Constants.js @@ -343,5 +343,7 @@ export default { DTSC: 'dtsc', AVC: 'avc', HEVC: 'hevc' - } + }, + MPD_CALLBACK_SCHEME: 'urn:mpeg:dash:event:callback:2015', + MPD_CALLBACK_VALUE: 1, } From 13ad341a2cd61ab68e5a8f3a7674ebab80cb6b9a Mon Sep 17 00:00:00 2001 From: Constanza Dibueno Date: Mon, 17 Mar 2025 14:47:48 -0300 Subject: [PATCH 4/9] sendCallbackRequest unit test --- .../streaming.controllers.EventController.js | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/test/unit/test/streaming/streaming.controllers.EventController.js b/test/unit/test/streaming/streaming.controllers.EventController.js index 1d94d27306..e95d70e0fd 100644 --- a/test/unit/test/streaming/streaming.controllers.EventController.js +++ b/test/unit/test/streaming/streaming.controllers.EventController.js @@ -6,12 +6,13 @@ import ManifestUpdaterMock from '../../mocks/ManifestUpdaterMock.js'; import Settings from '../../../../src/core/Settings.js'; import {expect} from 'chai'; +import sinon from 'sinon'; const context = {}; const eventBus = EventBus(context).getInstance(); describe('EventController', function () { let eventController; - + let manifestUpdaterMock = new ManifestUpdaterMock(); let playbackControllerMock = new PlaybackControllerMock(); const settings = Settings(context).getInstance(); @@ -575,5 +576,52 @@ describe('EventController', function () { eventBus.off(MediaPlayerEvents.MANIFEST_VALIDITY_CHANGED, manifestValidityExpiredHandler, this); }); + + it('should fire callback event', async function () { + const periodId = 'periodId'; + let events = [{ + eventStream: { + timescale: 3, + schemeIdUri: 'urn:mpeg:dash:event:callback:2015', + period: { + id: periodId + }, + value: 1, + }, + id: 'event0', + calculatedPresentationTime: 0, + duration: 5, + value: 'https://example.com/api', + triggeredReceivedEvent: true + }]; + + const xhrStub = sinon.useFakeXMLHttpRequest(); + let requests = []; + + xhrStub.onCreate = function (xhr) { + requests.push(xhr); + setTimeout(() => { + xhr.respond(200, { 'Content-Type': 'application/json' }, JSON.stringify({ success: true })); + }); + }; + + eventController.addInbandEvents(events, periodId); + + await new Promise(resolve => { + const checkRequest = () => { + if (requests.some(req => req.url === events[0].value)) { + resolve(); + } else { + setImmediate(checkRequest); + } + }; + checkRequest(); + }); + + expect(requests.some(req => req.url === events[0].value)).to.be.true; + + xhrStub.restore(); + }); + }); }); From 5d99028b41af5a8360ecb299c9e26ee8b6cca655 Mon Sep 17 00:00:00 2001 From: Constanza Dibueno Date: Thu, 20 Mar 2025 11:57:44 -0300 Subject: [PATCH 5/9] query parameters on callback unit test --- .../test/streaming/streaming.net.XHRLoader.js | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/test/unit/test/streaming/streaming.net.XHRLoader.js b/test/unit/test/streaming/streaming.net.XHRLoader.js index 804aac8989..55c52af97f 100644 --- a/test/unit/test/streaming/streaming.net.XHRLoader.js +++ b/test/unit/test/streaming/streaming.net.XHRLoader.js @@ -1,14 +1,20 @@ import XHRLoader from '../../../../src/streaming/net/XHRLoader.js'; - +import ExtUrlQueryInfoController from '../../../../src/streaming/controllers/ExtUrlQueryInfoController.js'; import {expect} from 'chai'; import sinon from 'sinon'; const context = {}; let xhrLoader; +let extUrlQueryInfoController; + describe('XHRLoader', function () { + before(() => { + extUrlQueryInfoController = ExtUrlQueryInfoController(context).getInstance(); + }); + beforeEach(function () { window.XMLHttpRequest = sinon.useFakeXMLHttpRequest(); @@ -111,4 +117,61 @@ describe('XHRLoader', function () { xhrLoader.load(request, {}); expect(xhrLoader.getXhr().timeout).to.be.equal(100); }); + + it('should add query parameters to callback request', function () { + const manifest = { + url: 'http://manifesturl.com/Manifest.mpd?urlParam1=urlValue1', + Period : [{ + AdaptationSet: [ + { + Representation: [{},{}] + }, + { + Representation: [{},{}] + }, + ], + }], + SupplementalProperty: [{ + schemeIdUri: 'urn:mpeg:dash:urlparam:2016', + ExtUrlQueryInfo: { + tagName: 'UrlQueryInfo', + queryTemplate: '$querypart$', + useMPDUrlQuery: 'true', + queryString: 'callbackParam=callbackParamValue', + includeInRequests: 'callback', + } + }], + }; + extUrlQueryInfoController.createFinalQueryStrings(manifest); + + const httpRequest = { + url: 'https://example.com/api', + type: 'callback', + representation: { + index: 0, + adaptation: { + index: 0, + period: { + index: 0 + } + } + }, + customData: { + periodIndex: 0 + } + }; + + const xhrStub = sinon.useFakeXMLHttpRequest(); + xhrStub.onCreate = function (xhr) { + setTimeout(() => { + xhr.respond(200, { 'Content-Type': 'application/json' }, JSON.stringify({ success: true })); + }); + }; + + xhrLoader = XHRLoader(context).create({}); + xhrLoader.load(httpRequest, {}); + + expect(httpRequest.url).to.include('?'); + expect(httpRequest.url).to.match(/callbackParam=callbackParamValue&urlParam1=urlValue1/); + }); }); From dc2577e3d49a7f78c7ad54e72fc851c1003d4ab0 Mon Sep 17 00:00:00 2001 From: Tatiana Perera Date: Tue, 25 Mar 2025 11:34:24 -0300 Subject: [PATCH 6/9] Moved local constants to Constants file --- src/dash/DashAdapter.js | 2 +- src/streaming/constants/Constants.js | 6 ++++-- src/streaming/controllers/EventController.js | 10 ++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/dash/DashAdapter.js b/src/dash/DashAdapter.js index 4aca89f548..b6fd3e98b9 100644 --- a/src/dash/DashAdapter.js +++ b/src/dash/DashAdapter.js @@ -496,7 +496,7 @@ function DashAdapter() { const duration = eventBox.event_duration / timescale; const id = eventBox.id; - const messageData = schemeIdUri === constants.MPD_CALLBACK_SCHEME & eventBox.value ? eventBox.value : eventBox.message_data; + const messageData = schemeIdUri === constants.MPD_CALLBACK.SCHEME & eventBox.value ? eventBox.value : eventBox.message_data; event.eventStream = eventStream; event.eventStream.value = value; diff --git a/src/streaming/constants/Constants.js b/src/streaming/constants/Constants.js index 6ca0568d34..99042a1855 100644 --- a/src/streaming/constants/Constants.js +++ b/src/streaming/constants/Constants.js @@ -344,6 +344,8 @@ export default { AVC: 'avc', HEVC: 'hevc' }, - MPD_CALLBACK_SCHEME: 'urn:mpeg:dash:event:callback:2015', - MPD_CALLBACK_VALUE: 1, + MPD_CALLBACK: { + SCHEME: 'urn:mpeg:dash:event:callback:2015', + VALUE: 1, + } } diff --git a/src/streaming/controllers/EventController.js b/src/streaming/controllers/EventController.js index 347d03e835..2afe2c40f5 100644 --- a/src/streaming/controllers/EventController.js +++ b/src/streaming/controllers/EventController.js @@ -34,15 +34,13 @@ import Debug from '../../core/Debug.js'; import EventBus from '../../core/EventBus.js'; import MediaPlayerEvents from '../../streaming/MediaPlayerEvents.js'; import XHRLoader from '../net/XHRLoader.js'; +import Constants from '../constants/Constants.js'; function EventController() { const MPD_RELOAD_SCHEME = 'urn:mpeg:dash:event:2012'; const MPD_RELOAD_VALUE = 1; - const MPD_CALLBACK_SCHEME = 'urn:mpeg:dash:event:callback:2015'; - const MPD_CALLBACK_VALUE = 1; - const REMAINING_EVENTS_THRESHOLD = 300; const EVENT_HANDLED_STATES = { @@ -154,7 +152,7 @@ function EventController() { logger.error(e); } } - + /** * Iterate over a list of events and trigger the ones for which the presentation time is within the current timing interval * @param {object} events @@ -485,7 +483,7 @@ function EventController() { logger.debug(`Starting manifest refresh event ${eventId} at ${currentVideoTime}`); _refreshManifest(); } - } else if (event.eventStream.schemeIdUri === MPD_CALLBACK_SCHEME && event.eventStream.value == MPD_CALLBACK_VALUE) { + } else if (event.eventStream.schemeIdUri === Constants.MPD_CALLBACK.SCHEME && event.eventStream.value == Constants.MPD_CALLBACK.VALUE) { logger.debug(`Starting callback event ${eventId} at ${currentVideoTime}`); _sendCallbackRequest(event); } else { @@ -544,7 +542,7 @@ function EventController() { */ function _sendCallbackRequest(event) { try { - const url = event.parsedMessageData ?? event.value; + const url = event.parsedMessageData; if (!url) { throw new Error('callback request URL is missing or invalid.'); } From 94c71cf9a9d19f62a8e30c2b2a2a8d9936ea2dcc Mon Sep 17 00:00:00 2001 From: cotid-qualabs <121617928+cotid-qualabs@users.noreply.github.com> Date: Mon, 31 Mar 2025 13:17:16 -0300 Subject: [PATCH 7/9] Update src/dash/DashAdapter.js Co-authored-by: Sebastian Piquerez <89274285+sebastianpiq@users.noreply.github.com> --- src/dash/DashAdapter.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dash/DashAdapter.js b/src/dash/DashAdapter.js index b6fd3e98b9..a62aa3271e 100644 --- a/src/dash/DashAdapter.js +++ b/src/dash/DashAdapter.js @@ -511,7 +511,6 @@ function DashAdapter() { } else { event.parsedMessageData = (messageData instanceof Uint8Array) ? utf8ArrayToStr(messageData) : null; } - return event; } catch (e) { return null; From e72e2b4ef3f08f47d93603e5f1b300cbd83fca15 Mon Sep 17 00:00:00 2001 From: cotid-qualabs <121617928+cotid-qualabs@users.noreply.github.com> Date: Mon, 31 Mar 2025 13:17:26 -0300 Subject: [PATCH 8/9] Update src/streaming/controllers/EventController.js Co-authored-by: Sebastian Piquerez <89274285+sebastianpiq@users.noreply.github.com> --- src/streaming/controllers/EventController.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/streaming/controllers/EventController.js b/src/streaming/controllers/EventController.js index 2afe2c40f5..c6cac8be19 100644 --- a/src/streaming/controllers/EventController.js +++ b/src/streaming/controllers/EventController.js @@ -152,7 +152,6 @@ function EventController() { logger.error(e); } } - /** * Iterate over a list of events and trigger the ones for which the presentation time is within the current timing interval * @param {object} events From d922c72f4f6dfba7329dc7ed55cfbcb2d1d222ce Mon Sep 17 00:00:00 2001 From: cotid-qualabs <121617928+cotid-qualabs@users.noreply.github.com> Date: Mon, 31 Mar 2025 13:17:35 -0300 Subject: [PATCH 9/9] Update test/unit/test/streaming/streaming.controllers.EventController.js Co-authored-by: Sebastian Piquerez <89274285+sebastianpiq@users.noreply.github.com> --- .../unit/test/streaming/streaming.controllers.EventController.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/test/streaming/streaming.controllers.EventController.js b/test/unit/test/streaming/streaming.controllers.EventController.js index e95d70e0fd..60a1786858 100644 --- a/test/unit/test/streaming/streaming.controllers.EventController.js +++ b/test/unit/test/streaming/streaming.controllers.EventController.js @@ -12,7 +12,6 @@ const eventBus = EventBus(context).getInstance(); describe('EventController', function () { let eventController; - let manifestUpdaterMock = new ManifestUpdaterMock(); let playbackControllerMock = new PlaybackControllerMock(); const settings = Settings(context).getInstance();