OLD | NEW |
---|---|
(Empty) | |
1 /** | |
2 * Copyright 2017 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #import "RTCFileVideoCapturer.h" | |
12 | |
13 #import "WebRTC/RTCLogging.h" | |
14 | |
15 @implementation RTCFileVideoCapturer { | |
16 AVAssetReader *_reader; | |
17 CMTime _lastPresentationTime; | |
18 dispatch_queue_t _frameQueue; | |
19 dispatch_semaphore_t _frameSemaphore; | |
20 BOOL _capturerStopped; | |
21 } | |
22 | |
23 - (void)startCapturingFromFileNamed:(NSString *)nameOfFile { | |
24 if (_reader && _reader.status == AVAssetReaderStatusReading) { | |
sakal
2017/05/23 09:37:18
Can this be moved inside the dispatch, then _reade
daniela-webrtc
2017/05/24 08:23:00
Done.
| |
25 RTCLog("Capturer exists and reads anoth6er file. Start capture request faile d."); | |
26 return; | |
27 } | |
28 | |
29 _lastPresentationTime = CMTimeMake(0, 0); | |
30 _frameSemaphore = dispatch_semaphore_create(0); | |
31 | |
32 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ | |
33 NSString *pathForFile = [self pathForFileName:nameOfFile]; | |
34 if (!pathForFile) { | |
35 RTCLog("File %@ not found in bundle", nameOfFile); | |
36 return; | |
37 } | |
38 | |
39 NSURL *URLForFile = [NSURL fileURLWithPath:pathForFile]; | |
40 AVURLAsset *asset = [AVURLAsset URLAssetWithURL:URLForFile options:nil]; | |
41 | |
42 NSArray *allTracks = [asset tracksWithMediaType:AVMediaTypeVideo]; | |
43 NSError *error = nil; | |
44 _reader = [[AVAssetReader alloc] initWithAsset:asset error:&error]; | |
45 if (error) { | |
46 RTCLog("File reader failed with error: %@", error); | |
47 return; | |
48 } | |
49 | |
50 NSDictionary *options = @{ | |
51 (NSString *) | |
52 kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanar VideoRange) | |
53 }; | |
54 AVAssetReaderTrackOutput *outTrack = | |
55 [[AVAssetReaderTrackOutput alloc] initWithTrack:allTracks.firstObject | |
56 outputSettings:options]; | |
57 [_reader addOutput:outTrack]; | |
58 | |
59 [_reader startReading]; | |
60 RTCLog(@"File capturer started reading"); | |
61 while (_reader.status == AVAssetReaderStatusReading && !_capturerStopped) { | |
62 CMSampleBufferRef sampleBuffer = [outTrack copyNextSampleBuffer]; | |
63 if (sampleBuffer) { | |
64 if (CMSampleBufferGetNumSamples(sampleBuffer) != 1 || | |
65 !CMSampleBufferIsValid(sampleBuffer) || !CMSampleBufferDataIsReady(s ampleBuffer)) { | |
66 continue; | |
67 } | |
68 | |
69 CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer ); | |
70 if (pixelBuffer == nil) { | |
71 continue; | |
72 } | |
73 | |
74 CMTime presentationTime = CMSampleBufferGetPresentationTimeStamp(sampleB uffer); | |
75 Float64 presentationDifference = | |
76 CMTimeGetSeconds(CMTimeSubtract(presentationTime, _lastPresentationT ime)); | |
77 int64_t presentationDifferenceRound = lroundf(presentationDifference * N SEC_PER_SEC); | |
78 _lastPresentationTime = presentationTime; | |
79 | |
80 // dispatch with delay, we want to achieve a real time play. | |
81 dispatch_after( | |
82 dispatch_time(DISPATCH_TIME_NOW, presentationDifferenceRound), [self frameQueue], ^{ | |
83 int64_t timeStampNs = CACurrentMediaTime() * NSEC_PER_SEC; | |
84 RTCVideoFrame *videoFrame = [[RTCVideoFrame alloc] initWithPixelBu ffer:pixelBuffer | |
85 rota tion:0 | |
86 timeSta mpNs:timeStampNs]; | |
87 CFRelease(sampleBuffer); | |
88 | |
89 [self.delegate capturer:self didCaptureVideoFrame:videoFrame]; | |
90 dispatch_semaphore_signal(_frameSemaphore); | |
91 }); | |
92 | |
93 dispatch_semaphore_wait(_frameSemaphore, DISPATCH_TIME_FOREVER); | |
94 } | |
95 } | |
96 [_reader cancelReading]; | |
97 _reader = nil; | |
98 }); | |
99 } | |
100 | |
101 - (void)stopCapture { | |
102 _capturerStopped = YES; | |
103 RTCLog(@"File capturer stopped."); | |
104 } | |
105 | |
106 #pragma mark - Private | |
107 | |
108 - (nullable NSString *)pathForFileName:(NSString *)fileName { | |
109 NSArray *nameComponents = [fileName componentsSeparatedByString:@"."]; | |
110 if (nameComponents.count != 2) { | |
111 return nil; | |
112 } | |
113 | |
114 NSString *path = | |
115 [[NSBundle mainBundle] pathForResource:nameComponents[0] ofType:nameCompon ents[1]]; | |
116 return path; | |
117 } | |
118 | |
119 - (dispatch_queue_t)frameQueue { | |
120 if (!_frameQueue) { | |
121 _frameQueue = dispatch_queue_create("org.webrtc.filecapturer.video", DISPATC H_QUEUE_SERIAL); | |
122 dispatch_set_target_queue(_frameQueue, | |
123 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_ BACKGROUND, 0)); | |
124 } | |
125 return _frameQueue; | |
126 } | |
127 | |
128 - (void)dealloc { | |
129 [self stopCapture]; | |
130 } | |
131 | |
132 @end | |
OLD | NEW |