@npaw/forge-react-native 9.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +10 -0
- package/NPAWForgeReactNative.podspec +44 -0
- package/README.md +51 -0
- package/android/build.gradle +77 -0
- package/android/src/main/AndroidManifest.xml +14 -0
- package/android/src/main/java/com/npaw/forge/reactnative/ForgeDtoMapper.java +295 -0
- package/android/src/main/java/com/npaw/forge/reactnative/ForgeInstanceRegistry.java +61 -0
- package/android/src/main/java/com/npaw/forge/reactnative/NPAWForgeModule.java +735 -0
- package/android/src/main/java/com/npaw/forge/reactnative/NPAWForgePackage.java +53 -0
- package/android/src/test/java/com/npaw/forge/reactnative/ForgeDtoMapperTest.java +133 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/Info.plist +82 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64/Headers/ForgeKernelFFI.h +17 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64/Headers/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64/Headers/module.modulemap +7 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64_x86_64-simulator/Headers/ForgeKernelFFI.h +17 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64_x86_64-simulator/Headers/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64_x86_64-simulator/Headers/module.modulemap +7 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/ios-arm64_x86_64-simulator/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64/Headers/ForgeKernelFFI.h +17 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64/Headers/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64/Headers/module.modulemap +7 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64-simulator/Headers/ForgeKernelFFI.h +17 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64-simulator/Headers/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64-simulator/Headers/module.modulemap +7 -0
- package/ios/ForgeApple/ForgeKernelFFI.xcframework/tvos-arm64-simulator/libForgeKernelFFI.a +0 -0
- package/ios/ForgeApple/Sources/ForgeKernelUniFFI/forge_kernel.swift +3931 -0
- package/ios/ForgeApple/Sources/ForgeKernelUniFFI/forge_kernelFFI.h +873 -0
- package/ios/ForgeApple/Sources/ForgeKernelUniFFI/forge_kernelFFI.modulemap +7 -0
- package/ios/ForgeApple/Sources/NPAWForgeAVPlayerAdapter/AVPlayerAccessLogFacts.swift +152 -0
- package/ios/ForgeApple/Sources/NPAWForgeAVPlayerAdapter/AVPlayerAdapter.swift +877 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/AttributionCapture.swift +158 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/CapturePlanGate.swift +189 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/CrashCapture.swift +120 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/ForgeAutomaticCapture.swift +639 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SectionsCapture.swift +1176 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SectionsEngine.swift +674 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SectionsMarkers.swift +105 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SectionsSwiftUI.swift +284 -0
- package/ios/ForgeApple/Sources/NPAWForgeCapture/SwiftUICapture.swift +44 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/AdAdapter.swift +199 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/AdSemantics.swift +136 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeApple.swift +596 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeCapturePlan.swift +297 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeClock.swift +29 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeLogging.swift +109 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeOutcome.swift +89 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeRuntime.swift +291 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ForgeStorage.swift +70 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ManualAdReporter.swift +180 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/NPAWForge.swift +453 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/NativeUniFFIRuntime.swift +594 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/NetworkRequestRecord.swift +191 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/ObjectiveCWrappers.swift +191 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/PlayerAdapter.swift +299 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/PlayerSemantics.swift +266 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/PrivacySanitizer.swift +59 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/VideoAdapter.swift +478 -0
- package/ios/ForgeApple/Sources/NPAWForgeCore/VideoOptions.swift +431 -0
- package/ios/ForgeApple/Sources/NPAWForgeNetworkCapture/ForgeNetworkCapture.swift +116 -0
- package/ios/ForgeApple/Sources/NPAWForgeNetworkCaptureObjC/NPAWForgeNetworkSwizzler.m +293 -0
- package/ios/ForgeApple/Sources/NPAWForgeNetworkCaptureObjC/include/NPAWForgeNetworkSwizzler.h +33 -0
- package/ios/ForgeModuleImpl.swift +1131 -0
- package/ios/NPAWForgeTurboModule.mm +399 -0
- package/package.json +33 -0
- package/src/ForgeAdReporter.ts +101 -0
- package/src/ForgeVideo.ts +169 -0
- package/src/NPAWForge.ts +177 -0
- package/src/capture.ts +192 -0
- package/src/events.ts +40 -0
- package/src/index.ts +37 -0
- package/src/specs/NativeNPAWForge.ts +168 -0
- package/src/types.ts +114 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (C) NPAW - All Rights Reserved
|
|
3
|
+
*
|
|
4
|
+
* This source code is protected under international copyright law. All rights
|
|
5
|
+
* reserved and protected by the copyright holders.
|
|
6
|
+
* This file is confidential and only available to authorized individuals with the
|
|
7
|
+
* permission of the copyright holders. If you encounter this file and do not have
|
|
8
|
+
* permission, please contact the copyright holders and delete this file.
|
|
9
|
+
*
|
|
10
|
+
*
|
|
11
|
+
* @author: Victor Soto <victor.soto@nicepeopleatwork.com>
|
|
12
|
+
* @description: Pure resolution rules turning AVPlayerItem access-log events into Forge media-bitrate and QoS facts, keeping the media bitrate strictly separate from the observed network throughput.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import AVFoundation
|
|
16
|
+
import Foundation
|
|
17
|
+
|
|
18
|
+
/// One access-log event reduced to the fields Forge derives facts from.
|
|
19
|
+
///
|
|
20
|
+
/// `AVPlayerItemAccessLogEvent` cannot be constructed in tests, so the adapter
|
|
21
|
+
/// maps every event through this struct and the resolution rules below operate
|
|
22
|
+
/// on it. That makes the rules deterministically testable without a live
|
|
23
|
+
/// `AVPlayer`.
|
|
24
|
+
///
|
|
25
|
+
/// Field semantics are quoted from `AVFoundation/AVPlayerItem.h`; every one of
|
|
26
|
+
/// them is documented as **negative if unknown**, which is why the rules filter
|
|
27
|
+
/// on `> 0` and not merely on `isFinite`.
|
|
28
|
+
struct AVPlayerAccessLogSample: Equatable {
|
|
29
|
+
/// `c-duration-downloaded` — "The accumulated duration of the media
|
|
30
|
+
/// downloaded", in **media** seconds. Combined with the transferred byte
|
|
31
|
+
/// count this yields a media bitrate, not a transfer rate.
|
|
32
|
+
let segmentsDownloadedDuration: Double
|
|
33
|
+
/// `c-bytes` — accumulated bytes transferred for the item.
|
|
34
|
+
let numberOfBytesTransferred: Int64
|
|
35
|
+
/// `sc-indicated-bitrate` — "The throughput required to play the stream,
|
|
36
|
+
/// as advertised by the server". Despite the header's wording this is the
|
|
37
|
+
/// **declared media bitrate** of the selected variant.
|
|
38
|
+
let indicatedBitrate: Double
|
|
39
|
+
/// `c-avg-video-bitrate` — the average video bitrate actually observed for
|
|
40
|
+
/// the item. Unambiguously a media bitrate, and the only tier that covers
|
|
41
|
+
/// progressive (non-HLS) assets, which advertise no variant bitrate.
|
|
42
|
+
let averageVideoBitrate: Double
|
|
43
|
+
/// `c-observed-bitrate` — "The empirical throughput across all media
|
|
44
|
+
/// downloaded". This is **network throughput**, never a media bitrate.
|
|
45
|
+
/// Forge reports it as `throughput`; publishing it as `bitrate` was the
|
|
46
|
+
/// defect this file exists to prevent.
|
|
47
|
+
let observedBitrate: Double
|
|
48
|
+
/// Dropped video frames reported for this event.
|
|
49
|
+
let numberOfDroppedVideoFrames: Int
|
|
50
|
+
|
|
51
|
+
init(
|
|
52
|
+
segmentsDownloadedDuration: Double,
|
|
53
|
+
numberOfBytesTransferred: Int64,
|
|
54
|
+
indicatedBitrate: Double,
|
|
55
|
+
averageVideoBitrate: Double,
|
|
56
|
+
observedBitrate: Double,
|
|
57
|
+
numberOfDroppedVideoFrames: Int
|
|
58
|
+
) {
|
|
59
|
+
self.segmentsDownloadedDuration = segmentsDownloadedDuration
|
|
60
|
+
self.numberOfBytesTransferred = numberOfBytesTransferred
|
|
61
|
+
self.indicatedBitrate = indicatedBitrate
|
|
62
|
+
self.averageVideoBitrate = averageVideoBitrate
|
|
63
|
+
self.observedBitrate = observedBitrate
|
|
64
|
+
self.numberOfDroppedVideoFrames = numberOfDroppedVideoFrames
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
init(_ event: AVPlayerItemAccessLogEvent) {
|
|
68
|
+
self.init(
|
|
69
|
+
segmentsDownloadedDuration: event.segmentsDownloadedDuration,
|
|
70
|
+
numberOfBytesTransferred: event.numberOfBytesTransferred,
|
|
71
|
+
indicatedBitrate: event.indicatedBitrate,
|
|
72
|
+
averageVideoBitrate: event.averageVideoBitrate,
|
|
73
|
+
observedBitrate: event.observedBitrate,
|
|
74
|
+
numberOfDroppedVideoFrames: event.numberOfDroppedVideoFrames
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/// Stateless resolution rules over access-log samples.
|
|
80
|
+
///
|
|
81
|
+
/// Kept free of adapter state so each rule is independently testable and so the
|
|
82
|
+
/// bitrate path cannot accidentally reach for the throughput field.
|
|
83
|
+
enum AVPlayerAccessLogFacts {
|
|
84
|
+
/// A finite, strictly positive reading, or `nil`. AVFoundation documents
|
|
85
|
+
/// every access-log metric as negative when unknown, and a `0` reading is
|
|
86
|
+
/// equally meaningless as a published fact.
|
|
87
|
+
private static func positive(_ value: Double) -> Double? {
|
|
88
|
+
guard value.isFinite, value > 0 else { return nil }
|
|
89
|
+
return value
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/// The media bitrate of the content being played, resolved by tiers. The
|
|
93
|
+
/// first tier that yields a finite positive value wins; `nil` means unknown
|
|
94
|
+
/// and the caller must keep the last known-good value rather than publish
|
|
95
|
+
/// a zero.
|
|
96
|
+
///
|
|
97
|
+
/// Tier 1 mirrors the v7 iOS plugin exactly (bytes * 8 / downloaded media
|
|
98
|
+
/// duration) so migrating integrations keep metric continuity. Tier 2 is
|
|
99
|
+
/// v7's own fallback and matches Forge's Flutter access-log enricher. Tier 3
|
|
100
|
+
/// covers progressive assets, which declare no variant bitrate at all.
|
|
101
|
+
///
|
|
102
|
+
/// `observedBitrate` is deliberately absent from every tier: it is network
|
|
103
|
+
/// throughput, and reporting it here overstates the bitrate by orders of
|
|
104
|
+
/// magnitude and swings run-to-run on byte-identical content.
|
|
105
|
+
static func mediaBitrate(from sample: AVPlayerAccessLogSample) -> Int64? {
|
|
106
|
+
if sample.numberOfBytesTransferred > 0,
|
|
107
|
+
let duration = positive(sample.segmentsDownloadedDuration) {
|
|
108
|
+
let derived = Double(sample.numberOfBytesTransferred) * 8.0 / duration
|
|
109
|
+
if let value = positive(derived) {
|
|
110
|
+
return Int64(value)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if let indicated = positive(sample.indicatedBitrate) {
|
|
114
|
+
return Int64(indicated)
|
|
115
|
+
}
|
|
116
|
+
if let average = positive(sample.averageVideoBitrate) {
|
|
117
|
+
return Int64(average)
|
|
118
|
+
}
|
|
119
|
+
return nil
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/// The empirical network throughput, which is what `observedBitrate`
|
|
123
|
+
/// actually measures.
|
|
124
|
+
static func observedThroughput(from sample: AVPlayerAccessLogSample) -> Double? {
|
|
125
|
+
positive(sample.observedBitrate)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/// Total dropped video frames across the item's access log. Returns `nil`
|
|
129
|
+
/// when no event reported a non-negative count, so "unknown" stays distinct
|
|
130
|
+
/// from a genuine zero.
|
|
131
|
+
static func droppedFrames(in samples: [AVPlayerAccessLogSample]) -> Int64? {
|
|
132
|
+
var total: Int64 = 0
|
|
133
|
+
var sawValue = false
|
|
134
|
+
for sample in samples where sample.numberOfDroppedVideoFrames >= 0 {
|
|
135
|
+
total += Int64(sample.numberOfDroppedVideoFrames)
|
|
136
|
+
sawValue = true
|
|
137
|
+
}
|
|
138
|
+
return sawValue ? total : nil
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/// Total bytes transferred across the item's access log, or `nil` when no
|
|
142
|
+
/// event reported a non-negative count.
|
|
143
|
+
static func totalBytes(in samples: [AVPlayerAccessLogSample]) -> Int64? {
|
|
144
|
+
var total: Int64 = 0
|
|
145
|
+
var sawValue = false
|
|
146
|
+
for sample in samples where sample.numberOfBytesTransferred >= 0 {
|
|
147
|
+
total += sample.numberOfBytesTransferred
|
|
148
|
+
sawValue = true
|
|
149
|
+
}
|
|
150
|
+
return sawValue ? total : nil
|
|
151
|
+
}
|
|
152
|
+
}
|