Skip to content

Commit 600400c

Browse files
committed
perf(dash-wasm): pass scalar attributes directly to JavaScript
1 parent 1688d3c commit 600400c

17 files changed

Lines changed: 158 additions & 191 deletions

File tree

‎src/parsers/manifest/dash/wasm-parser/rs/lib.rs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ extern "C" {
4949
/// * `len` - Length of the data - starting at `ptr` - in bytes.
5050
fn onAttribute(attr_name: AttributeName, ptr: *const u8, len: usize);
5151

52+
/// JS callback called when a numeric attribute has been parsed.
53+
fn onFloatAttribute(attr_name: AttributeName, value: f64);
54+
55+
/// JS callback called when a boolean attribute has been parsed.
56+
fn onBooleanAttribute(attr_name: AttributeName, value: u32);
57+
5258
/// JS callback for other specific operations, for example logging and warnings.
5359
///
5460
/// # Arguments

‎src/parsers/manifest/dash/wasm-parser/rs/reportable.rs‎

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::events::AttributeName;
2-
use crate::onAttribute;
32
use crate::processor::SegmentObject;
3+
use crate::{onAttribute, onBooleanAttribute, onFloatAttribute};
44
use core::mem;
55
use std::borrow::Cow;
66

@@ -37,11 +37,8 @@ impl ReportableAttribute for bool {
3737
fn report_as_attr(&self, attr_name: AttributeName) {
3838
debug_assert!(attr_name as u64 <= u8::MAX as u64);
3939

40-
let val: u8 = if *self { 1 } else { 0 };
41-
// UNSAFE: We're using FFI, so we don't know how the pointer is used.
42-
// Hopefully, the JavaScript-side should clone that value synchronously.
4340
unsafe {
44-
onAttribute(attr_name, &val, 1);
41+
onBooleanAttribute(attr_name, u32::from(*self));
4542
};
4643
}
4744
}
@@ -51,16 +48,8 @@ impl ReportableAttribute for f64 {
5148
fn report_as_attr(&self, attr_name: AttributeName) {
5249
debug_assert!(attr_name as u64 <= u8::MAX as u64);
5350

54-
// UNSAFE: We're using FFI, so we don't know how the pointer is used.
55-
// Hopefully, the JavaScript-side should clone that value synchronously.
56-
//
57-
// Also, we're casting so that the f64 value is actually treated as if it
58-
// was a *const u8 (immutable raw pointer to an u8) as it's what the JS
59-
// callback expects.
60-
// This should not matter: Rust types are not communicated to
61-
// JavaScript anyway.
6251
unsafe {
63-
onAttribute(attr_name, self as *const f64 as *const u8, 8);
52+
onFloatAttribute(attr_name, *self);
6453
};
6554
}
6655
}

‎src/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.ts‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ export default class DashWasmParser {
154154
onTagOpen,
155155
onCustomEvent,
156156
onAttribute,
157+
onFloatAttribute,
158+
onBooleanAttribute,
157159
readNext,
158160
onTagClose,
159161
},
@@ -251,6 +253,14 @@ export default class DashWasmParser {
251253
return parsersStack.attributeParser(attr, ptr, len);
252254
}
253255

256+
function onFloatAttribute(attr: AttributeName, value: number): void {
257+
parsersStack.attributeParser(attr, 0, 0, value);
258+
}
259+
260+
function onBooleanAttribute(attr: AttributeName, value: number): void {
261+
parsersStack.attributeParser(attr, 0, 0, value);
262+
}
263+
254264
/**
255265
* Callback called on the various "custom events" triggered by the WASM.
256266
*

‎src/parsers/manifest/dash/wasm-parser/ts/generators/AdaptationSet.ts‎

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import type {
2323
import type { IAttributeParser, IChildrenParser } from "../parsers_stack.ts";
2424
import type ParsersStack from "../parsers_stack.ts";
2525
import { AttributeName, TagName } from "../types.ts";
26-
import { parseFloatOrBool, parseString } from "../utils.ts";
26+
import { parseFloatOrBool, parseString, readBoolean, readFloat } from "../utils.ts";
2727
import { generateBaseUrlAttrParser } from "./BaseURL.ts";
2828
import { generateContentComponentAttrParser } from "./ContentComponent.ts";
2929
import { generateContentProtectionAttrParser } from "./ContentProtection.ts";
@@ -256,14 +256,18 @@ export function generateAdaptationSetAttrParser(
256256
adaptationAttrs: IAdaptationSetAttributes,
257257
linearMemory: WebAssembly.Memory,
258258
): IAttributeParser {
259-
return function onAdaptationSetAttribute(attr: number, ptr: number, len: number) {
260-
const dataView = new DataView(linearMemory.buffer);
259+
return function onAdaptationSetAttribute(
260+
attr: number,
261+
ptr: number,
262+
len: number,
263+
value?: number,
264+
) {
261265
switch (attr) {
262266
case AttributeName.Id:
263267
adaptationAttrs.id = parseString(linearMemory.buffer, ptr, len);
264268
break;
265269
case AttributeName.Group:
266-
adaptationAttrs.group = dataView.getFloat64(ptr, true);
270+
adaptationAttrs.group = readFloat(value);
267271
break;
268272
case AttributeName.Language:
269273
adaptationAttrs.lang = parseString(linearMemory.buffer, ptr, len);
@@ -275,44 +279,40 @@ export function generateAdaptationSetAttrParser(
275279
adaptationAttrs.par = parseString(linearMemory.buffer, ptr, len);
276280
break;
277281
case AttributeName.MinBandwidth:
278-
adaptationAttrs.minBandwidth = dataView.getFloat64(ptr, true);
282+
adaptationAttrs.minBandwidth = readFloat(value);
279283
break;
280284
case AttributeName.MaxBandwidth:
281-
adaptationAttrs.maxBandwidth = dataView.getFloat64(ptr, true);
285+
adaptationAttrs.maxBandwidth = readFloat(value);
282286
break;
283287
case AttributeName.MinWidth:
284-
adaptationAttrs.minWidth = dataView.getFloat64(ptr, true);
288+
adaptationAttrs.minWidth = readFloat(value);
285289
break;
286290
case AttributeName.MaxWidth:
287-
adaptationAttrs.maxWidth = dataView.getFloat64(ptr, true);
291+
adaptationAttrs.maxWidth = readFloat(value);
288292
break;
289293
case AttributeName.MinHeight:
290-
adaptationAttrs.minHeight = dataView.getFloat64(ptr, true);
294+
adaptationAttrs.minHeight = readFloat(value);
291295
break;
292296
case AttributeName.MaxHeight:
293-
adaptationAttrs.maxHeight = dataView.getFloat64(ptr, true);
297+
adaptationAttrs.maxHeight = readFloat(value);
294298
break;
295299
case AttributeName.MinFrameRate:
296-
adaptationAttrs.minFrameRate = dataView.getFloat64(ptr, true);
300+
adaptationAttrs.minFrameRate = readFloat(value);
297301
break;
298302
case AttributeName.MaxFrameRate:
299-
adaptationAttrs.maxFrameRate = dataView.getFloat64(ptr, true);
303+
adaptationAttrs.maxFrameRate = readFloat(value);
300304
break;
301305
case AttributeName.SelectionPriority:
302-
adaptationAttrs.selectionPriority = dataView.getFloat64(ptr, true);
306+
adaptationAttrs.selectionPriority = readFloat(value);
303307
break;
304308
case AttributeName.SegmentAlignment:
305-
adaptationAttrs.segmentAlignment = parseFloatOrBool(
306-
dataView.getFloat64(ptr, true),
307-
);
309+
adaptationAttrs.segmentAlignment = parseFloatOrBool(readFloat(value));
308310
break;
309311
case AttributeName.SubsegmentAlignment:
310-
adaptationAttrs.subsegmentAlignment = parseFloatOrBool(
311-
dataView.getFloat64(ptr, true),
312-
);
312+
adaptationAttrs.subsegmentAlignment = parseFloatOrBool(readFloat(value));
313313
break;
314314
case AttributeName.BitstreamSwitching:
315-
adaptationAttrs.bitstreamSwitching = dataView.getUint8(ptr) !== 0;
315+
adaptationAttrs.bitstreamSwitching = readBoolean(value);
316316
break;
317317
case AttributeName.AudioSamplingRate:
318318
adaptationAttrs.audioSamplingRate = parseString(linearMemory.buffer, ptr, len);
@@ -337,28 +337,28 @@ export function generateAdaptationSetAttrParser(
337337
adaptationAttrs.mimeType = parseString(linearMemory.buffer, ptr, len);
338338
break;
339339
case AttributeName.CodingDependency:
340-
adaptationAttrs.codingDependency = dataView.getUint8(ptr) !== 0;
340+
adaptationAttrs.codingDependency = readBoolean(value);
341341
break;
342342
case AttributeName.FrameRate:
343-
adaptationAttrs.frameRate = dataView.getFloat64(ptr, true);
343+
adaptationAttrs.frameRate = readFloat(value);
344344
break;
345345
case AttributeName.Height:
346-
adaptationAttrs.height = dataView.getFloat64(ptr, true);
346+
adaptationAttrs.height = readFloat(value);
347347
break;
348348
case AttributeName.Width:
349-
adaptationAttrs.width = dataView.getFloat64(ptr, true);
349+
adaptationAttrs.width = readFloat(value);
350350
break;
351351
case AttributeName.MaxPlayoutRate:
352-
adaptationAttrs.maxPlayoutRate = dataView.getFloat64(ptr, true);
352+
adaptationAttrs.maxPlayoutRate = readFloat(value);
353353
break;
354354
case AttributeName.MaxSAPPeriod:
355-
adaptationAttrs.maximumSAPPeriod = dataView.getFloat64(ptr, true);
355+
adaptationAttrs.maximumSAPPeriod = readFloat(value);
356356
break;
357357
case AttributeName.AvailabilityTimeOffset:
358-
adaptationAttrs.availabilityTimeOffset = dataView.getFloat64(ptr, true);
358+
adaptationAttrs.availabilityTimeOffset = readFloat(value);
359359
break;
360360
case AttributeName.AvailabilityTimeComplete:
361-
adaptationAttrs.availabilityTimeComplete = dataView.getUint8(ptr) !== 0;
361+
adaptationAttrs.availabilityTimeComplete = readBoolean(value);
362362
break;
363363
}
364364
};

‎src/parsers/manifest/dash/wasm-parser/ts/generators/EventStream.ts‎

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import type {
2323
import type { IAttributeParser, IChildrenParser } from "../parsers_stack.ts";
2424
import type ParsersStack from "../parsers_stack.ts";
2525
import { AttributeName, TagName } from "../types.ts";
26-
import { parseString } from "../utils.ts";
26+
import { parseString, readFloat } from "../utils.ts";
2727

2828
/**
2929
* Generate a "children parser" once inside a `EventStream` node.
@@ -67,7 +67,12 @@ export function generateEventStreamAttrParser(
6767
esAttrs: IEventStreamAttributes,
6868
linearMemory: WebAssembly.Memory,
6969
): IAttributeParser {
70-
return function onEventStreamAttribute(attr: number, ptr: number, len: number) {
70+
return function onEventStreamAttribute(
71+
attr: number,
72+
ptr: number,
73+
len: number,
74+
value?: number,
75+
) {
7176
const dataView = new DataView(linearMemory.buffer);
7277
switch (attr) {
7378
case AttributeName.SchemeIdUri:
@@ -77,7 +82,7 @@ export function generateEventStreamAttrParser(
7782
esAttrs.value = parseString(linearMemory.buffer, ptr, len);
7883
break;
7984
case AttributeName.TimeScale:
80-
esAttrs.timescale = dataView.getFloat64(ptr, true);
85+
esAttrs.timescale = readFloat(value);
8186
break;
8287
case AttributeName.Namespace: {
8388
const xmlNs = { key: "", value: "" };
@@ -114,14 +119,19 @@ function generateEventAttrParser(
114119
linearMemory: WebAssembly.Memory,
115120
fullMpd: ArrayBufferLike,
116121
): IAttributeParser {
117-
return function onEventStreamAttribute(attr: number, ptr: number, len: number) {
122+
return function onEventStreamAttribute(
123+
attr: number,
124+
ptr: number,
125+
len: number,
126+
value?: number,
127+
) {
118128
const dataView = new DataView(linearMemory.buffer);
119129
switch (attr) {
120130
case AttributeName.EventPresentationTime:
121-
eventAttr.presentationTime = dataView.getFloat64(ptr, true);
131+
eventAttr.presentationTime = readFloat(value);
122132
break;
123133
case AttributeName.Duration:
124-
eventAttr.duration = dataView.getFloat64(ptr, true);
134+
eventAttr.duration = readFloat(value);
125135
break;
126136
case AttributeName.Id:
127137
eventAttr.id = parseString(linearMemory.buffer, ptr, len);

‎src/parsers/manifest/dash/wasm-parser/ts/generators/MPD.ts‎

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import type {
2424
import type { IAttributeParser, IChildrenParser } from "../parsers_stack.ts";
2525
import type ParsersStack from "../parsers_stack.ts";
2626
import { AttributeName, TagName } from "../types.ts";
27-
import { parseString } from "../utils.ts";
27+
import { parseString, readFloat } from "../utils.ts";
2828
import { generateBaseUrlAttrParser } from "./BaseURL.ts";
2929
import { generateContentProtectionAttrParser } from "./ContentProtection.ts";
3030
import { generatePeriodAttrParser, generatePeriodChildrenParser } from "./Period.ts";
@@ -121,7 +121,7 @@ export function generateMPDAttrParser(
121121
linearMemory: WebAssembly.Memory,
122122
): IAttributeParser {
123123
let dataView;
124-
return function onMPDAttribute(attr: number, ptr: number, len: number) {
124+
return function onMPDAttribute(attr: number, ptr: number, len: number, value?: number) {
125125
switch (attr) {
126126
case AttributeName.Id:
127127
mpdAttrs.id = parseString(linearMemory.buffer, ptr, len);
@@ -148,32 +148,25 @@ export function generateMPDAttrParser(
148148
break;
149149
}
150150
case AttributeName.MediaPresentationDuration:
151-
dataView = new DataView(linearMemory.buffer);
152-
mpdAttrs.mediaPresentationDuration = dataView.getFloat64(ptr, true);
151+
mpdAttrs.mediaPresentationDuration = readFloat(value);
153152
break;
154153
case AttributeName.MinimumUpdatePeriod:
155-
dataView = new DataView(linearMemory.buffer);
156-
mpdAttrs.minimumUpdatePeriod = dataView.getFloat64(ptr, true);
154+
mpdAttrs.minimumUpdatePeriod = readFloat(value);
157155
break;
158156
case AttributeName.MinBufferTime:
159-
dataView = new DataView(linearMemory.buffer);
160-
mpdAttrs.minBufferTime = dataView.getFloat64(ptr, true);
157+
mpdAttrs.minBufferTime = readFloat(value);
161158
break;
162159
case AttributeName.TimeShiftBufferDepth:
163-
dataView = new DataView(linearMemory.buffer);
164-
mpdAttrs.timeShiftBufferDepth = dataView.getFloat64(ptr, true);
160+
mpdAttrs.timeShiftBufferDepth = readFloat(value);
165161
break;
166162
case AttributeName.SuggestedPresentationDelay:
167-
dataView = new DataView(linearMemory.buffer);
168-
mpdAttrs.suggestedPresentationDelay = dataView.getFloat64(ptr, true);
163+
mpdAttrs.suggestedPresentationDelay = readFloat(value);
169164
break;
170165
case AttributeName.MaxSegmentDuration:
171-
dataView = new DataView(linearMemory.buffer);
172-
mpdAttrs.maxSegmentDuration = dataView.getFloat64(ptr, true);
166+
mpdAttrs.maxSegmentDuration = readFloat(value);
173167
break;
174168
case AttributeName.MaxSubsegmentDuration:
175-
dataView = new DataView(linearMemory.buffer);
176-
mpdAttrs.maxSubsegmentDuration = dataView.getFloat64(ptr, true);
169+
mpdAttrs.maxSubsegmentDuration = readFloat(value);
177170
break;
178171
case AttributeName.Location: {
179172
const location = parseString(linearMemory.buffer, ptr, len);

‎src/parsers/manifest/dash/wasm-parser/ts/generators/Period.ts‎

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import type {
2323
import type { IAttributeParser, IChildrenParser } from "../parsers_stack.ts";
2424
import type ParsersStack from "../parsers_stack.ts";
2525
import { AttributeName, TagName } from "../types.ts";
26-
import { parseString } from "../utils.ts";
26+
import { parseString, readBoolean, readFloat } from "../utils.ts";
2727
import {
2828
generateAdaptationSetAttrParser,
2929
generateAdaptationSetChildrenParser,
@@ -164,20 +164,19 @@ export function generatePeriodAttrParser(
164164
periodAttrs: IPeriodAttributes,
165165
linearMemory: WebAssembly.Memory,
166166
): IAttributeParser {
167-
return function onPeriodAttribute(attr, ptr, len) {
167+
return function onPeriodAttribute(attr, ptr, len, value) {
168168
switch (attr) {
169169
case AttributeName.Id:
170170
periodAttrs.id = parseString(linearMemory.buffer, ptr, len);
171171
break;
172172
case AttributeName.Start:
173-
periodAttrs.start = new DataView(linearMemory.buffer).getFloat64(ptr, true);
173+
periodAttrs.start = readFloat(value);
174174
break;
175175
case AttributeName.Duration:
176-
periodAttrs.duration = new DataView(linearMemory.buffer).getFloat64(ptr, true);
176+
periodAttrs.duration = readFloat(value);
177177
break;
178178
case AttributeName.BitstreamSwitching:
179-
periodAttrs.bitstreamSwitching =
180-
new DataView(linearMemory.buffer).getUint8(ptr) !== 0;
179+
periodAttrs.bitstreamSwitching = readBoolean(value);
181180
break;
182181
case AttributeName.XLinkHref:
183182
periodAttrs["xlink:href"] = parseString(linearMemory.buffer, ptr, len);
@@ -186,14 +185,10 @@ export function generatePeriodAttrParser(
186185
periodAttrs["xlink:actuate"] = parseString(linearMemory.buffer, ptr, len);
187186
break;
188187
case AttributeName.AvailabilityTimeOffset:
189-
periodAttrs.availabilityTimeOffset = new DataView(linearMemory.buffer).getFloat64(
190-
ptr,
191-
true,
192-
);
188+
periodAttrs.availabilityTimeOffset = readFloat(value);
193189
break;
194190
case AttributeName.AvailabilityTimeComplete:
195-
periodAttrs.availabilityTimeComplete =
196-
new DataView(linearMemory.buffer).getUint8(ptr) !== 0;
191+
periodAttrs.availabilityTimeComplete = readBoolean(value);
197192
break;
198193
case AttributeName.Namespace: {
199194
const xmlNs = { key: "", value: "" };

0 commit comments

Comments
 (0)