c43dd3ca4a
A native iOS receiver so an iPhone can act as the second receiver, speaking the existing signaling + RTP protocol (no C++ changes) and mirroring the Android receiver (Phase 8) source-to-source. - RTP core (header/packet, jitter buffer, H.264 depacketizer) ported from the Android receiver - BSD-socket signaling server (dual-stack, most-recent-peer, never-throwing sends) + NSBonjourServices - VideoToolbox H.264 decode (in-band SPS/PPS, real-time, rebuilds on size change) -> AVSampleBufferDisplayLayer - PLI keyframe recovery (500 ms) + pendingOffer for late surface attach - XcodeGen project + bootstrap.sh; XCTest port of the Android suite + new coverage - .gitignore for generated artifacts; CHANGELOG; PHASES + MEMORY updated Status: authored; on-device validation pending a Mac + Xcode 26 + iPhone 16.
30 lines
926 B
Swift
30 lines
926 B
Swift
import Foundation
|
|
|
|
/// The in-band SPS (type 7) and PPS (type 8) NAL units extracted from an
|
|
/// access unit. The sender repeats both ahead of every keyframe, so any
|
|
/// keyframe carries them; they are the source for the VideoToolbox format
|
|
/// description.
|
|
struct NalSets {
|
|
let sps: [UInt8]
|
|
let pps: [UInt8]
|
|
}
|
|
|
|
/// Extracts parameter sets from an Annex-B access unit.
|
|
enum NalExtractor {
|
|
static func parameterSets(_ annexB: [UInt8]) -> NalSets? {
|
|
var sps: [UInt8]?
|
|
var pps: [UInt8]?
|
|
for nal in AvccConverter.nalUnits(annexB) {
|
|
guard !nal.isEmpty else { continue }
|
|
let type = Int(nal[0]) & 0x1F
|
|
if type == 7 && sps == nil {
|
|
sps = nal
|
|
} else if type == 8 && pps == nil {
|
|
pps = nal
|
|
}
|
|
}
|
|
guard let s = sps, let p = pps else { return nil }
|
|
return NalSets(sps: s, pps: p)
|
|
}
|
|
}
|