Skip to content

Commit bb7cb18

Browse files
committed
Initial checking.
0 parents  commit bb7cb18

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2264
-0
lines changed

.gitignore

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
/*.xcodeproj
5+
DerivedData/
6+
*.pbxuser
7+
!default.pbxuser
8+
*.mode1v3
9+
!default.mode1v3
10+
*.mode2v3
11+
!default.mode2v3
12+
*.perspectivev3
13+
!default.perspectivev3
14+
xcuserdata/
15+
*.moved-aside
16+
*.xccheckout
17+
*.xcscmblueprint
18+
*.hmap
19+
*.ipa
20+
*.dSYM.zip
21+
*.dSYM
22+
timeline.xctimeline
23+
playground.xcworkspace
24+
*.xcodeproj/*
25+
!*.xcodeproj/project.pbxproj
26+
!*.xcodeproj/xcshareddata/
27+
!*.xcworkspace/contents.xcworkspacedata
28+
/*.gcno
29+
*.mp4
30+
*.mov
31+
*.m4v
32+
Package.resolved
33+

Package.swift

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// swift-tools-version:4.0
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "morsel",
8+
products: [
9+
// Products define the executables and libraries produced by a package, and make them visible to other packages.
10+
.library(
11+
name: "morsel",
12+
targets: ["morsel"]),
13+
],
14+
dependencies: [
15+
// Dependencies declare other packages that this package depends on.
16+
// .package(url: /* package url */, from: "1.0.0"),
17+
],
18+
targets: [
19+
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
20+
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
21+
.target(
22+
name: "morsel",
23+
dependencies: []),
24+
.testTarget(
25+
name: "morselTests",
26+
dependencies: ["morsel"]),
27+
]
28+
)

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# morsel
2+
3+
A description of this package.

Sources/morsel/Atoms/AVC1.swift

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// FIXME
2+
struct AVC1: BinarySizedEncodable {
3+
4+
let type: Atom = .avc1
5+
6+
var reserved: [UInt8] = [0, 0, 0, 0, 0 ,0]
7+
8+
var dataReferenceIndex: UInt16 = 1
9+
var version: UInt16 = 0
10+
var revisionLevel: UInt16 = 0
11+
var vendor: UInt32 = 0
12+
var temporalQuality: UInt32 = 0
13+
var spatialQuality: UInt32 = 0
14+
15+
var width: UInt16 = 1281
16+
var height: UInt16 = 721
17+
var horizontalResolution: UInt32 = 4718592
18+
var verticalResolution: UInt32 = 4718592
19+
20+
var dataSize: UInt32 = 0
21+
var frameCount: UInt16 = 1
22+
var compressorNameSize: UInt8 = 0
23+
var padding: [UInt8] = [0, 0, 0, 0, 0, 0, 0, 0,
24+
0, 0, 0, 0, 0, 0, 0, 0,
25+
0, 0, 0, 0, 0, 0, 0, 0,
26+
0, 0, 0, 0, 0, 0, 0]
27+
28+
var depth: UInt16 = 24
29+
var colorTableID: UInt16 = 65535
30+
31+
var avcC: [AVCC] = [AVCC()]
32+
var colr: [COLR] = [COLR()]
33+
var pasp: [PASP] = [PASP()]
34+
35+
static func from(_ config: MOOVVideoSettings) -> AVC1 {
36+
var avc1 = AVC1()
37+
avc1.width = UInt16(config.width)
38+
avc1.height = UInt16(config.height)
39+
avc1.avcC = [AVCC.from(config)]
40+
return avc1
41+
}
42+
}

Sources/morsel/Atoms/AVCC.swift

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// AVC Decoder Configuration
2+
struct AVCC: BinarySizedEncodable {
3+
4+
let type: Atom = .avcC
5+
6+
var version: UInt8 = 1
7+
var profile: UInt8 = 77
8+
var profileCompatibility: UInt8 = 0
9+
var levelIndication: UInt8 = 31
10+
11+
var naluSize: UInt8 = 3 // NALUnitLength field in the parameter set minus 1
12+
var spsCount: UInt8 = 0xe1
13+
var spsLength: UInt16 = 27
14+
15+
var sps: [SPS] = [SPS(data: [0x27, 0x4d, 0x00, 0x1f, 0x89, 0x8b,
16+
0x60, 0x28, 0x02, 0xdd, 0x80, 0xb5,
17+
0x01, 0x01, 0x01, 0xec, 0x0c, 0x00,
18+
0x17, 0x70, 0x00, 0x05, 0xdc, 0x17,
19+
0xbd, 0xf0, 0x50])]
20+
21+
var ppsCount: UInt8 = 1
22+
var ppsLength: UInt16 = 4
23+
var pps: [PPS] = [PPS(data: [0x28, 0xee, 0x1f, 0x20])]
24+
25+
static func from(_ config: MOOVVideoSettings) -> AVCC {
26+
var avcc = AVCC()
27+
avcc.sps = [SPS(data: config.sps)]
28+
avcc.spsCount = 1
29+
avcc.spsLength = UInt16(config.sps.count)
30+
avcc.pps = [PPS(data: config.pps)]
31+
avcc.ppsCount = 1
32+
avcc.ppsLength = UInt16(config.pps.count)
33+
return avcc
34+
}
35+
36+
}
37+
38+
struct SPS: BinaryEncodable {
39+
var data: [UInt8]
40+
}
41+
42+
struct PPS: BinaryEncodable {
43+
var data: [UInt8]
44+
}

Sources/morsel/Atoms/COLR.swift

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// This atom is a required extension for uncompressed Y´CbCr data formats.
2+
// The 'colr' extension is used to map the numerical values of pixels in the file to a common representation of color in which images can be correctly compared, combined, and displayed.
3+
struct COLR: BinarySizedEncodable {
4+
5+
let type: Atom = .colr
6+
var colorParameter: ColorParameter = .videoBMFF
7+
8+
var primariesIndex: UInt16 = 1
9+
var transferFunctionIndex: UInt16 = 1
10+
var matrixIndex: UInt16 = 1
11+
12+
var unknown: UInt8 = 0
13+
}
14+
15+
enum ColorParameter: String, BinaryEncodable {
16+
case video = "nclc" // nonconstant luminance coding.
17+
case videoBMFF = "nclx" // ISO BMFF file
18+
case print = "prof"
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/// This comes from Mike Ash's work on implementing a Codeable implemention of a binary encoder/decoder
2+
/// https://github.com/mikeash/BinaryCoder
3+
/// https://www.mikeash.com/pyblog/friday-qa-2017-07-28-a-binary-coder-for-swift.html
4+
5+
/// Implementations of BinaryCodable for built-in types.
6+
import Foundation
7+
8+
extension Array: BinaryEncodable {
9+
public func binaryEncode(to encoder: BinaryEncoder) throws {
10+
guard Element.self is Encodable.Type else {
11+
throw BinaryEncoder.Error.typeNotConformingToEncodable(Element.self)
12+
}
13+
14+
if Element.self is BinarySizedEncodable.Type {
15+
for element in self {
16+
let newEncoder = BinaryEncoder()
17+
try (element as! Encodable).encode(to: newEncoder)
18+
try encoder.encode(UInt32(newEncoder.data.count + 4))
19+
try newEncoder.data.encode(to: encoder)
20+
}
21+
22+
} else {
23+
for element in self {
24+
try (element as! Encodable).encode(to: encoder)
25+
}
26+
}
27+
}
28+
}
29+
30+
extension String: BinaryEncodable {
31+
public func binaryEncode(to encoder: BinaryEncoder) throws {
32+
try Array(self.utf8).binaryEncode(to: encoder)
33+
}
34+
}
35+
36+
extension FixedWidthInteger where Self: BinaryEncodable {
37+
public func binaryEncode(to encoder: BinaryEncoder) {
38+
encoder.appendBytes(of: self.bigEndian)
39+
}
40+
}
41+
42+
extension Int8: BinaryEncodable {}
43+
extension UInt8: BinaryEncodable {}
44+
extension Int16: BinaryEncodable {}
45+
extension UInt16: BinaryEncodable {}
46+
extension Int32: BinaryEncodable {}
47+
extension UInt32: BinaryEncodable {}
48+
extension Int64: BinaryEncodable {}
49+
extension UInt64: BinaryEncodable {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/// This comes from Mike Ash's work on implementing a Codeable implemention of a binary encoder/decoder
2+
/// https://github.com/mikeash/BinaryCoder
3+
/// https://www.mikeash.com/pyblog/friday-qa-2017-07-28-a-binary-coder-for-swift.html
4+
5+
import CoreFoundation
6+
7+
8+
/// A protocol for types which can be encoded to binary.
9+
public protocol BinaryEncodable: Encodable {
10+
func binaryEncode(to encoder: BinaryEncoder) throws
11+
}
12+
13+
/// This is used when an atom has children that need to be prefixed by their size
14+
public protocol BinarySizedEncodable: BinaryEncodable { }
15+
16+
/// Provide a default implementation which calls through to `Encodable`. This
17+
/// allows `BinaryEncodable` to use the `Encodable` implementation generated by the
18+
/// compiler.
19+
public extension BinaryEncodable {
20+
func binaryEncode(to encoder: BinaryEncoder) throws {
21+
try self.encode(to: encoder)
22+
}
23+
}
24+
25+
/// The actual binary encoder class.
26+
public class BinaryEncoder {
27+
internal var data: [UInt8] = []
28+
29+
public init() {}
30+
}
31+
32+
/// A convenience function for creating an encoder, encoding a value, and
33+
/// extracting the resulting data.
34+
public extension BinaryEncoder {
35+
static func encode(_ value: BinaryEncodable) throws -> [UInt8] {
36+
let encoder = BinaryEncoder()
37+
try value.binaryEncode(to: encoder)
38+
39+
// KRAD: We need to prepend the size of what we've encoded
40+
return byteArray(from: UInt32(encoder.data.count + 4)) + encoder.data
41+
}
42+
}
43+
44+
/// The error type.
45+
public extension BinaryEncoder {
46+
/// All errors which `BinaryEncoder` itself can throw.
47+
enum Error: Swift.Error {
48+
/// Attempted to encode a type which is `Encodable`, but not `BinaryEncodable`. (We
49+
/// require `BinaryEncodable` because `BinaryEncoder` doesn't support full keyed
50+
/// coding functionality.)
51+
case typeNotConformingToBinaryEncodable(Encodable.Type)
52+
53+
/// Attempted to encode a type which is not `Encodable`.
54+
case typeNotConformingToEncodable(Any.Type)
55+
}
56+
}
57+
58+
/// Methods for encoding various types.
59+
public extension BinaryEncoder {
60+
func encode(_ value: Bool) throws {
61+
try encode(value ? 1 as UInt8 : 0 as UInt8)
62+
}
63+
64+
func encode(_ value: Float) {
65+
appendBytes(of: CFConvertFloatHostToSwapped(value))
66+
}
67+
68+
func encode(_ value: Double) {
69+
appendBytes(of: CFConvertDoubleHostToSwapped(value))
70+
}
71+
72+
func encode(_ encodable: Encodable) throws {
73+
switch encodable {
74+
case let v as Int:
75+
try encode(Int64(v))
76+
case let v as UInt:
77+
try encode(UInt64(v))
78+
case let v as Float:
79+
encode(v)
80+
case let v as Double:
81+
encode(v)
82+
case let v as Bool:
83+
try encode(v)
84+
case let binary as BinaryEncodable:
85+
try binary.binaryEncode(to: self)
86+
default:
87+
throw Error.typeNotConformingToBinaryEncodable(type(of: encodable))
88+
}
89+
}
90+
91+
/// Append the raw bytes of the parameter to the encoder's data. No byte-swapping
92+
/// or other encoding is done.
93+
func appendBytes<T>(of: T) {
94+
var target = of
95+
withUnsafeBytes(of: &target) {
96+
data.append(contentsOf: $0)
97+
}
98+
}
99+
}
100+
101+
extension BinaryEncoder: Encoder {
102+
public var codingPath: [CodingKey] { return [] }
103+
104+
public var userInfo: [CodingUserInfoKey : Any] { return [:] }
105+
106+
public func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {
107+
return KeyedEncodingContainer(KeyedContainer<Key>(encoder: self))
108+
}
109+
110+
public func unkeyedContainer() -> UnkeyedEncodingContainer {
111+
return UnkeyedContanier(encoder: self)
112+
}
113+
114+
public func singleValueContainer() -> SingleValueEncodingContainer {
115+
return UnkeyedContanier(encoder: self)
116+
}
117+
118+
private struct KeyedContainer<Key: CodingKey>: KeyedEncodingContainerProtocol {
119+
var encoder: BinaryEncoder
120+
121+
var codingPath: [CodingKey] { return [] }
122+
123+
func encode<T>(_ value: T, forKey key: Key) throws where T : Encodable {
124+
try encoder.encode(value)
125+
}
126+
127+
func encodeNil(forKey key: Key) throws {}
128+
129+
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
130+
return encoder.container(keyedBy: keyType)
131+
}
132+
133+
func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
134+
return encoder.unkeyedContainer()
135+
}
136+
137+
func superEncoder() -> Encoder {
138+
return encoder
139+
}
140+
141+
func superEncoder(forKey key: Key) -> Encoder {
142+
return encoder
143+
}
144+
}
145+
146+
private struct UnkeyedContanier: UnkeyedEncodingContainer, SingleValueEncodingContainer {
147+
var encoder: BinaryEncoder
148+
149+
var codingPath: [CodingKey] { return [] }
150+
151+
var count: Int { return 0 }
152+
153+
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
154+
return encoder.container(keyedBy: keyType)
155+
}
156+
157+
func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
158+
return self
159+
}
160+
161+
func superEncoder() -> Encoder {
162+
return encoder
163+
}
164+
165+
func encodeNil() throws {}
166+
167+
func encode<T>(_ value: T) throws where T : Encodable {
168+
try encoder.encode(value)
169+
}
170+
}
171+
}

0 commit comments

Comments
 (0)