mirror of
https://github.com/aculix/knotchy.git
synced 2026-10-27 07:15:53 +00:00
Initial release
This commit is contained in:
commit
4b67728cce
108 files changed
+13310
No files matched your search
@@ -0,0 +1,108 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
@testable import KnotchyCore
|
||||
|
||||
struct H264Tests {
|
||||
private let aud: [UInt8] = [0x09, 0xF0]
|
||||
private let sei: [UInt8] = [0x06, 0x05, 0x01, 0xAA, 0x80]
|
||||
private let sps: [UInt8] = [0x67, 0x42, 0xC0, 0x1F, 0x8C]
|
||||
private let sps2: [UInt8] = [0x67, 0x42, 0xC0, 0x28, 0x8C]
|
||||
private let pps: [UInt8] = [0x68, 0xCE, 0x3C, 0x80]
|
||||
private let pps2: [UInt8] = [0x68, 0xCE, 0x3C, 0x81]
|
||||
private let idr: [UInt8] = [0x65, 0x88, 0x84, 0x21]
|
||||
private let slice: [UInt8] = [0x41, 0x9A, 0x02]
|
||||
|
||||
private let four: [UInt8] = [0, 0, 0, 1]
|
||||
private let three: [UInt8] = [0, 0, 1]
|
||||
|
||||
private func avcc(_ nals: [UInt8]...) -> Data {
|
||||
nals.reduce(into: Data()) { data, nal in
|
||||
data.appendBE32(UInt32(nal.count))
|
||||
data.append(contentsOf: nal)
|
||||
}
|
||||
}
|
||||
|
||||
@Test func splitsOnThreeAndFourByteStartCodes() {
|
||||
let stream = Data(four + aud + three + sps + four + pps + three + idr)
|
||||
#expect(AnnexB.nalUnits(in: stream) == [aud, sps, pps, idr].map { Data($0) })
|
||||
}
|
||||
|
||||
@Test func ignoresLeadingBytesAndTrailingZeros() {
|
||||
let stream = Data([0xFF, 0x00] + three + slice + [0, 0] + four + slice + [0])
|
||||
#expect(AnnexB.nalUnits(in: stream) == [Data(slice), Data(slice)])
|
||||
}
|
||||
|
||||
@Test func handlesStreamsWithoutStartCodes() {
|
||||
#expect(AnnexB.nalUnits(in: Data()) == [])
|
||||
#expect(AnnexB.nalUnits(in: Data([0x65, 0x88])) == [])
|
||||
#expect(AnnexB.nalUnits(in: Data(four)) == [])
|
||||
#expect(AnnexB.nalUnits(in: Data(three + idr + three)) == [Data(idr)])
|
||||
}
|
||||
|
||||
@Test func turnsAnIDRAccessUnitIntoAnAVCCSampleWithNewParameterSets() {
|
||||
var parser = H264Parser()
|
||||
let unit = parser.parse(Data(four + aud + four + sps + four + pps + four + sei + four + idr + four + idr))
|
||||
#expect(unit.sample == avcc(idr, idr))
|
||||
#expect(unit.isIDR)
|
||||
#expect(unit.newParameterSets == ParameterSets(sps: Data(sps), pps: Data(pps)))
|
||||
#expect(parser.parameterSets == unit.newParameterSets)
|
||||
}
|
||||
|
||||
@Test func repeatedParameterSetsAreNotAChange() {
|
||||
var parser = H264Parser()
|
||||
_ = parser.parse(Data(four + sps + four + pps + four + idr))
|
||||
let again = parser.parse(Data(four + aud + four + sps + four + pps + four + idr))
|
||||
#expect(again.newParameterSets == nil)
|
||||
let delta = parser.parse(Data(four + aud + four + slice))
|
||||
#expect(delta.sample == avcc(slice))
|
||||
#expect(!delta.isIDR)
|
||||
#expect(delta.newParameterSets == nil)
|
||||
// Repeated with every IDR: not a change, so the decoder isn't rebuilt.
|
||||
let nextIDR = parser.parse(Data(four + aud + four + sps + four + pps + four + idr))
|
||||
#expect(nextIDR.newParameterSets == nil)
|
||||
}
|
||||
|
||||
@Test func aChangedSPSOrPPSIsANewFormat() {
|
||||
var parser = H264Parser()
|
||||
_ = parser.parse(Data(four + sps + four + pps + four + idr))
|
||||
let changedSPS = parser.parse(Data(four + sps2 + four + pps + four + idr))
|
||||
#expect(changedSPS.newParameterSets == ParameterSets(sps: Data(sps2), pps: Data(pps)))
|
||||
let changedPPS = parser.parse(Data(four + sps2 + four + pps2 + four + idr))
|
||||
#expect(changedPPS.newParameterSets == ParameterSets(sps: Data(sps2), pps: Data(pps2)))
|
||||
}
|
||||
|
||||
@Test func aHalfPairIsNeverAFormat() {
|
||||
var parser = H264Parser()
|
||||
let spsOnly = parser.parse(Data(four + sps + four + idr))
|
||||
#expect(spsOnly.newParameterSets == nil)
|
||||
#expect(parser.parameterSets == nil)
|
||||
|
||||
_ = parser.parse(Data(four + sps + four + pps + four + idr))
|
||||
let lone = parser.parse(Data(four + sps2 + four + slice))
|
||||
#expect(lone.newParameterSets == nil)
|
||||
#expect(parser.parameterSets == ParameterSets(sps: Data(sps), pps: Data(pps)))
|
||||
}
|
||||
|
||||
@Test func onlyValidSliceUnitsAreDecoded() {
|
||||
var parser = H264Parser()
|
||||
// Type 21, a 3D extension slice.
|
||||
let extensionSlice = parser.parse(Data(four + [0x75, 0x88]))
|
||||
#expect(extensionSlice.sample.isEmpty)
|
||||
#expect(!extensionSlice.isIDR)
|
||||
// Forbidden bit set.
|
||||
let forbidden = parser.parse(Data(four + [0xE5, 0x88] + four + slice))
|
||||
#expect(forbidden.sample == avcc(slice))
|
||||
#expect(!forbidden.isIDR)
|
||||
#expect(parser.parse(Data(four + idr + four + slice)).isIDR)
|
||||
let long = [UInt8(0x41)] + [UInt8](repeating: 0x9A, count: 299)
|
||||
#expect(parser.parse(Data(four + long)).sample.prefix(4) == Data([0, 0, 0x01, 0x2C]))
|
||||
}
|
||||
|
||||
@Test func slicesBeforeAnyParameterSetsHaveNoFormat() {
|
||||
var parser = H264Parser()
|
||||
let unit = parser.parse(Data(four + slice))
|
||||
#expect(unit.sample == avcc(slice))
|
||||
#expect(unit.newParameterSets == nil)
|
||||
#expect(parser.parameterSets == nil)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user