1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
//
// SDLVideoEncoderSpec.m
// SmartDeviceLink-iOS
//
// Created by Muller, Alexander (A.) on 2/7/17.
// Copyright © 2017 smartdevicelink. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import <Quick/Quick.h>
#import <Nimble/Nimble.h>
#import <OCMock/OCMock.h>
#import "SDLH264VideoEncoder.h"
#import "SDLRAWH264Packetizer.h"
#import "SDLRTPH264Packetizer.h"
#import "SDLVideoStreamingProtocol.h"
@interface SDLH264VideoEncoder ()
@property (assign, nonatomic) NSUInteger currentFrameNumber;
@property (assign, nonatomic) double timestampOffset;
@property (assign, nonatomic, nullable) VTCompressionSessionRef compressionSession;
@end
QuickSpecBegin(SDLH264VideoEncoderSpec)
describe(@"a video encoder", ^{
__block SDLH264VideoEncoder *testVideoEncoder = nil;
__block CGSize testSize = CGSizeZero;
__block UInt32 testSSRC = 234;
__block id videoEncoderDelegateMock = OCMProtocolMock(@protocol(SDLVideoEncoderDelegate));
__block NSError *testError = nil;
__block SDLVideoStreamingProtocol testProtocol = nil;
beforeEach(^{
testSize = CGSizeMake(100, 200);
testProtocol = SDLVideoStreamingProtocolRAW;
testError = nil;
});
context(@"if using default video encoder settings", ^{
beforeEach(^{
testVideoEncoder = [[SDLH264VideoEncoder alloc] initWithProtocol:testProtocol dimensions:testSize ssrc:testSSRC properties:SDLH264VideoEncoder.defaultVideoEncoderSettings delegate:videoEncoderDelegateMock error:&testError];
});
it(@"should initialize properties", ^{
expect(testVideoEncoder).toNot(beNil());
expect(testVideoEncoder.videoEncoderSettings).to(equal(SDLH264VideoEncoder.defaultVideoEncoderSettings));
expect(@(testVideoEncoder.pixelBufferPool == NULL)).to(equal(@NO));
expect(testError).to(beNil());
expect(testVideoEncoder.packetizer).to(beAnInstanceOf([SDLRAWH264Packetizer class]));
NSDictionary *pixelBufferProperties = (__bridge NSDictionary*)CVPixelBufferPoolGetPixelBufferAttributes(testVideoEncoder.pixelBufferPool);
expect(pixelBufferProperties[(__bridge NSString*)kCVPixelBufferWidthKey]).to(equal(@100));
expect(pixelBufferProperties[(__bridge NSString*)kCVPixelBufferHeightKey]).to(equal(@200));
});
context(@"when stopping", ^{
beforeEach(^{
[testVideoEncoder stop];
});
it(@"should reset the saved properties", ^{
expect(testVideoEncoder.currentFrameNumber).to(equal(0));
expect(testVideoEncoder.timestampOffset).to(equal(0.0));
expect((id)testVideoEncoder.compressionSession).to(beNil());
});
});
});
describe(@"is using custom video encoder settings", ^{
__block NSDictionary *testSettings = nil;
context(@"that is a valid setting", ^{
beforeEach(^{
testSettings = @{
(__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1
};
testVideoEncoder = [[SDLH264VideoEncoder alloc] initWithProtocol:testProtocol dimensions:testSize ssrc:testSSRC properties:testSettings delegate:videoEncoderDelegateMock error:&testError];
});
it(@"should initialize properties", ^{
expect(testVideoEncoder).toNot(beNil());
expect(testVideoEncoder.videoEncoderSettings).to(equal(testSettings));
expect(@(testVideoEncoder.pixelBufferPool == NULL)).to(equal(@NO));
expect(testError).to(beNil());
NSDictionary *pixelBufferProperties = (__bridge NSDictionary*)CVPixelBufferPoolGetPixelBufferAttributes(testVideoEncoder.pixelBufferPool);
expect(pixelBufferProperties[(__bridge NSString*)kCVPixelBufferWidthKey]).to(equal(@100));
expect(pixelBufferProperties[(__bridge NSString*)kCVPixelBufferHeightKey]).to(equal(@200));
});
});
context(@"that is not a valid setting", ^{
beforeEach(^{
testSettings = @{
@"Bad" : @"Property"
};
testVideoEncoder = [[SDLH264VideoEncoder alloc] initWithProtocol:testProtocol dimensions:testSize ssrc:testSSRC properties:testSettings delegate:videoEncoderDelegateMock error:&testError];
});
it(@"should not be initialized", ^{
expect(testVideoEncoder).to(beNil());
expect(testError).to(equal([NSError errorWithDomain:SDLErrorDomainVideoEncoder code:SDLVideoEncoderErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{ NSLocalizedDescriptionKey : @"\"Bad\" is not a supported key." }]));
});
});
});
context(@"using an unknown protocol", ^{
beforeEach(^{
testProtocol = SDLVideoStreamingProtocolRTSP;
testVideoEncoder = [[SDLH264VideoEncoder alloc] initWithProtocol:testProtocol dimensions:testSize ssrc:testSSRC properties:SDLH264VideoEncoder.defaultVideoEncoderSettings delegate:videoEncoderDelegateMock error:&testError];
});
it(@"should not be initialized", ^{
expect(testVideoEncoder).to(beNil());
expect(testError.code).to(equal(SDLVideoEncoderErrorProtocolUnknown));
expect(testError.userInfo[@"encoder"]).to(equal(testProtocol));
});
});
context(@"creating with RTP H264 Protocol", ^{
beforeEach(^{
testProtocol = SDLVideoStreamingProtocolRTP;
testVideoEncoder = [[SDLH264VideoEncoder alloc] initWithProtocol:testProtocol dimensions:testSize ssrc:testSSRC properties:SDLH264VideoEncoder.defaultVideoEncoderSettings delegate:videoEncoderDelegateMock error:&testError];
});
it(@"should create an RTP packetizer", ^{
expect(testVideoEncoder.packetizer).to(beAnInstanceOf([SDLRTPH264Packetizer class]));
});
});
});
QuickSpecEnd
|