Skip to content

Commit 95f8af0

Browse files
committed
perf(dash-wasm): pass scalar attributes directly to JavaScript
1 parent bc2ab3d commit 95f8af0

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";
@@ -257,14 +257,18 @@ export function generateAdaptationSetAttrParser(
257257
linearMemory: WebAssembly.Memory,
258258
): IAttributeParser {
259259
const textDecoder = new TextDecoder();
260-
return function onAdaptationSetAttribute(attr: number, ptr: number, len: number) {
261-
const dataView = new DataView(linearMemory.buffer);
260+
return function onAdaptationSetAttribute(
261+
attr: number,
262+
ptr: number,
263+
len: number,
264+
value?: number,
265+
) {
262266
switch (attr) {
263267
case AttributeName.Id:
264268
adaptationAttrs.id = parseString(textDecoder, linearMemory.buffer, ptr, len);
265269
break;
266270
case AttributeName.Group:
267-
adaptationAttrs.group = dataView.getFloat64(ptr, true);
271+
adaptationAttrs.group = readFloat(value);
268272
break;
269273
case AttributeName.Language:
270274
adaptationAttrs.lang = parseString(textDecoder, linearMemory.buffer, ptr, len);
@@ -281,44 +285,40 @@ export function generateAdaptationSetAttrParser(
281285
adaptationAttrs.par = parseString(textDecoder, linearMemory.buffer, ptr, len);
282286
break;
283287
case AttributeName.MinBandwidth:
284-
adaptationAttrs.minBandwidth = dataView.getFloat64(ptr, true);
288+
adaptationAttrs.minBandwidth = readFloat(value);
285289
break;
286290
case AttributeName.MaxBandwidth:
287-
adaptationAttrs.maxBandwidth = dataView.getFloat64(ptr, true);
291+
adaptationAttrs.maxBandwidth = readFloat(value);
288292
break;
289293
case AttributeName.MinWidth:
290-
adaptationAttrs.minWidth = dataView.getFloat64(ptr, true);
294+
adaptationAttrs.minWidth = readFloat(value);
291295
break;
292296
case AttributeName.MaxWidth:
293-
adaptationAttrs.maxWidth = dataView.getFloat64(ptr, true);
297+
adaptationAttrs.maxWidth = readFloat(value);
294298
break;
295299
case AttributeName.MinHeight:
296-
adaptationAttrs.minHeight = dataView.getFloat64(ptr, true);
300+
adaptationAttrs.minHeight = readFloat(value);
297301
break;
298302
case AttributeName.MaxHeight:
299-
adaptationAttrs.maxHeight = dataView.getFloat64(ptr, true);
303+
adaptationAttrs.maxHeight = readFloat(value);
300304
break;
301305
case AttributeName.MinFrameRate:
302-
adaptationAttrs.minFrameRate = dataView.getFloat64(ptr, true);
306+
adaptationAttrs.minFrameRate = readFloat(value);
303307
break;
304308
case AttributeName.MaxFrameRate:
305-
adaptationAttrs.maxFrameRate = dataView.getFloat64(ptr, true);
309+
adaptationAttrs.maxFrameRate = readFloat(value);
306310
break;
307311
case AttributeName.SelectionPriority:
308-
adaptationAttrs.selectionPriority = dataView.getFloat64(ptr, true);
312+
adaptationAttrs.selectionPriority = readFloat(value);
309313
break;
310314
case AttributeName.SegmentAlignment:
311-
adaptationAttrs.segmentAlignment = parseFloatOrBool(
312-
dataView.getFloat64(ptr, true),
313-
);
315+
adaptationAttrs.segmentAlignment = parseFloatOrBool(readFloat(value));
314316
break;
315317
case AttributeName.SubsegmentAlignment:
316-
adaptationAttrs.subsegmentAlignment = parseFloatOrBool(
317-
dataView.getFloat64(ptr, true),
318-
);
318+
adaptationAttrs.subsegmentAlignment = parseFloatOrBool(readFloat(value));
319319
break;
320320
case AttributeName.BitstreamSwitching:
321-
adaptationAttrs.bitstreamSwitching = dataView.getUint8(ptr) !== 0;
321+
adaptationAttrs.bitstreamSwitching = readBoolean(value);
322322
break;
323323
case AttributeName.AudioSamplingRate:
324324
adaptationAttrs.audioSamplingRate = parseString(
@@ -364,28 +364,28 @@ export function generateAdaptationSetAttrParser(
364364
);
365365
break;
366366
case AttributeName.CodingDependency:
367-
adaptationAttrs.codingDependency = dataView.getUint8(ptr) !== 0;
367+
adaptationAttrs.codingDependency = readBoolean(value);
368368
break;
369369
case AttributeName.FrameRate:
370-
adaptationAttrs.frameRate = dataView.getFloat64(ptr, true);
370+
adaptationAttrs.frameRate = readFloat(value);
371371
break;
372372
case AttributeName.Height:
373-
adaptationAttrs.height = dataView.getFloat64(ptr, true);
373+
adaptationAttrs.height = readFloat(value);
374374
break;
375375
case AttributeName.Width:
376-
adaptationAttrs.width = dataView.getFloat64(ptr, true);
376+
adaptationAttrs.width = readFloat(value);
377377
break;
378378
case AttributeName.MaxPlayoutRate:
379-
adaptationAttrs.maxPlayoutRate = dataView.getFloat64(ptr, true);
379+
adaptationAttrs.maxPlayoutRate = readFloat(value);
380380
break;
381381
case AttributeName.MaxSAPPeriod:
382-
adaptationAttrs.maximumSAPPeriod = dataView.getFloat64(ptr, true);
382+
adaptationAttrs.maximumSAPPeriod = readFloat(value);
383383
break;
384384
case AttributeName.AvailabilityTimeOffset:
385-
adaptationAttrs.availabilityTimeOffset = dataView.getFloat64(ptr, true);
385+
adaptationAttrs.availabilityTimeOffset = readFloat(value);
386386
break;
387387
case AttributeName.AvailabilityTimeComplete:
388-
adaptationAttrs.availabilityTimeComplete = dataView.getUint8(ptr) !== 0;
388+
adaptationAttrs.availabilityTimeComplete = readBoolean(value);
389389
break;
390390
}
391391
};

‎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.
@@ -68,7 +68,12 @@ export function generateEventStreamAttrParser(
6868
linearMemory: WebAssembly.Memory,
6969
): IAttributeParser {
7070
const textDecoder = new TextDecoder();
71-
return function onEventStreamAttribute(attr: number, ptr: number, len: number) {
71+
return function onEventStreamAttribute(
72+
attr: number,
73+
ptr: number,
74+
len: number,
75+
value?: number,
76+
) {
7277
const dataView = new DataView(linearMemory.buffer);
7378
switch (attr) {
7479
case AttributeName.SchemeIdUri:
@@ -78,7 +83,7 @@ export function generateEventStreamAttrParser(
7883
esAttrs.value = parseString(textDecoder, linearMemory.buffer, ptr, len);
7984
break;
8085
case AttributeName.TimeScale:
81-
esAttrs.timescale = dataView.getFloat64(ptr, true);
86+
esAttrs.timescale = readFloat(value);
8287
break;
8388
case AttributeName.Namespace: {
8489
const xmlNs = { key: "", value: "" };
@@ -116,14 +121,19 @@ function generateEventAttrParser(
116121
fullMpd: ArrayBufferLike,
117122
): IAttributeParser {
118123
const textDecoder = new TextDecoder();
119-
return function onEventStreamAttribute(attr: number, ptr: number, len: number) {
124+
return function onEventStreamAttribute(
125+
attr: number,
126+
ptr: number,
127+
len: number,
128+
value?: number,
129+
) {
120130
const dataView = new DataView(linearMemory.buffer);
121131
switch (attr) {
122132
case AttributeName.EventPresentationTime:
123-
eventAttr.presentationTime = dataView.getFloat64(ptr, true);
133+
eventAttr.presentationTime = readFloat(value);
124134
break;
125135
case AttributeName.Duration:
126-
eventAttr.duration = dataView.getFloat64(ptr, true);
136+
eventAttr.duration = readFloat(value);
127137
break;
128138
case AttributeName.Id:
129139
eventAttr.id = parseString(textDecoder, 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";
@@ -122,7 +122,7 @@ export function generateMPDAttrParser(
122122
): IAttributeParser {
123123
let dataView;
124124
const textDecoder = new TextDecoder();
125-
return function onMPDAttribute(attr: number, ptr: number, len: number) {
125+
return function onMPDAttribute(attr: number, ptr: number, len: number, value?: number) {
126126
switch (attr) {
127127
case AttributeName.Id:
128128
mpdAttrs.id = parseString(textDecoder, linearMemory.buffer, ptr, len);
@@ -149,32 +149,25 @@ export function generateMPDAttrParser(
149149
break;
150150
}
151151
case AttributeName.MediaPresentationDuration:
152-
dataView = new DataView(linearMemory.buffer);
153-
mpdAttrs.mediaPresentationDuration = dataView.getFloat64(ptr, true);
152+
mpdAttrs.mediaPresentationDuration = readFloat(value);
154153
break;
155154
case AttributeName.MinimumUpdatePeriod:
156-
dataView = new DataView(linearMemory.buffer);
157-
mpdAttrs.minimumUpdatePeriod = dataView.getFloat64(ptr, true);
155+
mpdAttrs.minimumUpdatePeriod = readFloat(value);
158156
break;
159157
case AttributeName.MinBufferTime:
160-
dataView = new DataView(linearMemory.buffer);
161-
mpdAttrs.minBufferTime = dataView.getFloat64(ptr, true);
158+
mpdAttrs.minBufferTime = readFloat(value);
162159
break;
163160
case AttributeName.TimeShiftBufferDepth:
164-
dataView = new DataView(linearMemory.buffer);
165-
mpdAttrs.timeShiftBufferDepth = dataView.getFloat64(ptr, true);
161+
mpdAttrs.timeShiftBufferDepth = readFloat(value);
166162
break;
167163
case AttributeName.SuggestedPresentationDelay:
168-
dataView = new DataView(linearMemory.buffer);
169-
mpdAttrs.suggestedPresentationDelay = dataView.getFloat64(ptr, true);
164+
mpdAttrs.suggestedPresentationDelay = readFloat(value);
170165
break;
171166
case AttributeName.MaxSegmentDuration:
172-
dataView = new DataView(linearMemory.buffer);
173-
mpdAttrs.maxSegmentDuration = dataView.getFloat64(ptr, true);
167+
mpdAttrs.maxSegmentDuration = readFloat(value);
174168
break;
175169
case AttributeName.MaxSubsegmentDuration:
176-
dataView = new DataView(linearMemory.buffer);
177-
mpdAttrs.maxSubsegmentDuration = dataView.getFloat64(ptr, true);
170+
mpdAttrs.maxSubsegmentDuration = readFloat(value);
178171
break;
179172
case AttributeName.Location: {
180173
const location = parseString(textDecoder, 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,
@@ -165,20 +165,19 @@ export function generatePeriodAttrParser(
165165
linearMemory: WebAssembly.Memory,
166166
): IAttributeParser {
167167
const textDecoder = new TextDecoder();
168-
return function onPeriodAttribute(attr, ptr, len) {
168+
return function onPeriodAttribute(attr, ptr, len, value) {
169169
switch (attr) {
170170
case AttributeName.Id:
171171
periodAttrs.id = parseString(textDecoder, linearMemory.buffer, ptr, len);
172172
break;
173173
case AttributeName.Start:
174-
periodAttrs.start = new DataView(linearMemory.buffer).getFloat64(ptr, true);
174+
periodAttrs.start = readFloat(value);
175175
break;
176176
case AttributeName.Duration:
177-
periodAttrs.duration = new DataView(linearMemory.buffer).getFloat64(ptr, true);
177+
periodAttrs.duration = readFloat(value);
178178
break;
179179
case AttributeName.BitstreamSwitching:
180-
periodAttrs.bitstreamSwitching =
181-
new DataView(linearMemory.buffer).getUint8(ptr) !== 0;
180+
periodAttrs.bitstreamSwitching = readBoolean(value);
182181
break;
183182
case AttributeName.XLinkHref:
184183
periodAttrs["xlink:href"] = parseString(
@@ -197,14 +196,10 @@ export function generatePeriodAttrParser(
197196
);
198197
break;
199198
case AttributeName.AvailabilityTimeOffset:
200-
periodAttrs.availabilityTimeOffset = new DataView(linearMemory.buffer).getFloat64(
201-
ptr,
202-
true,
203-
);
199+
periodAttrs.availabilityTimeOffset = readFloat(value);
204200
break;
205201
case AttributeName.AvailabilityTimeComplete:
206-
periodAttrs.availabilityTimeComplete =
207-
new DataView(linearMemory.buffer).getUint8(ptr) !== 0;
202+
periodAttrs.availabilityTimeComplete = readBoolean(value);
208203
break;
209204
case AttributeName.Namespace: {
210205
const xmlNs = { key: "", value: "" };

0 commit comments

Comments
 (0)