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; | |
sakal
2017/05/24 08:34:09
I think this should be a property declared as atom
daniela-webrtc
2017/06/01 13:08:57
Not necessarily. The worst thing that can happen i
| |
21 } | |
22 | |
23 - (void)startCapturingFromFileNamed:(NSString *)nameOfFile { | |
24 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ | |
25 if (_reader && _reader.status == AVAssetReaderStatusReading) { | |
26 RTCLog("Capturer exists and reads anoth6er file. Start capture request fai led."); | |
magjed_webrtc
2017/05/29 13:14:25
nit: anoth6er
daniela-webrtc
2017/06/01 13:08:57
Done.
| |
27 return; | |
28 } | |
29 NSString *pathForFile = [self pathForFileName:nameOfFile]; | |
30 if (!pathForFile) { | |
31 RTCLog("File %@ not found in bundle", nameOfFile); | |
32 return; | |
33 } | |
34 | |
35 _lastPresentationTime = CMTimeMake(0, 0); | |
36 _frameSemaphore = dispatch_semaphore_create(0); | |
37 | |
38 NSURL *URLForFile = [NSURL fileURLWithPath:pathForFile]; | |
39 AVURLAsset *asset = [AVURLAsset URLAssetWithURL:URLForFile options:nil]; | |
40 | |
41 NSArray *allTracks = [asset tracksWithMediaType:AVMediaTypeVideo]; | |
42 NSError *error = nil; | |
43 _reader = [[AVAssetReader alloc] initWithAsset:asset error:&error]; | |
44 if (error) { | |
45 RTCLog("File reader failed with error: %@", error); | |
46 return; | |
47 } | |
48 | |
49 NSDictionary *options = @{ | |
50 (NSString *) | |
51 kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanar VideoRange) | |
magjed_webrtc
2017/05/29 13:14:25
Is it possible to use FullRange?
daniela-webrtc
2017/06/01 13:08:57
Yes. I've changed it
| |
52 }; | |
53 AVAssetReaderTrackOutput *outTrack = | |
54 [[AVAssetReaderTrackOutput alloc] initWithTrack:allTracks.firstObject | |
55 outputSettings:options]; | |
56 [_reader addOutput:outTrack]; | |
57 | |
58 [_reader startReading]; | |
59 RTCLog(@"File capturer started reading"); | |
60 while (_reader.status == AVAssetReaderStatusReading && !_capturerStopped) { | |
61 CMSampleBufferRef sampleBuffer = [outTrack copyNextSampleBuffer]; | |
62 if (sampleBuffer) { | |
63 if (CMSampleBufferGetNumSamples(sampleBuffer) != 1 || | |
64 !CMSampleBufferIsValid(sampleBuffer) || !CMSampleBufferDataIsReady(s ampleBuffer)) { | |
65 continue; | |
66 } | |
67 | |
68 CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer ); | |
69 if (pixelBuffer == nil) { | |
70 continue; | |
71 } | |
72 | |
73 CMTime presentationTime = CMSampleBufferGetPresentationTimeStamp(sampleB uffer); | |
74 Float64 presentationDifference = | |
75 CMTimeGetSeconds(CMTimeSubtract(presentationTime, _lastPresentationT ime)); | |
76 int64_t presentationDifferenceRound = lroundf(presentationDifference * N SEC_PER_SEC); | |
77 _lastPresentationTime = presentationTime; | |
78 | |
79 // dispatch with delay, we want to achieve a real time play. | |
magjed_webrtc
2017/05/29 13:14:25
nit: Begin sentence with capital letter.
| |
80 dispatch_after( | |
81 dispatch_time(DISPATCH_TIME_NOW, presentationDifferenceRound), [self frameQueue], ^{ | |
82 int64_t timeStampNs = CACurrentMediaTime() * NSEC_PER_SEC; | |
83 RTCVideoFrame *videoFrame = [[RTCVideoFrame alloc] initWithPixelBu ffer:pixelBuffer | |
84 rota tion:0 | |
85 timeSta mpNs:timeStampNs]; | |
86 CFRelease(sampleBuffer); | |
87 | |
88 [self.delegate capturer:self didCaptureVideoFrame:videoFrame]; | |
89 dispatch_semaphore_signal(_frameSemaphore); | |
magjed_webrtc
2017/05/29 13:14:25
I would like to only use one frame queue and avoid
daniela-webrtc
2017/06/01 13:08:57
I've removed the semaphore and the blocking and no
magjed_webrtc
2017/06/01 13:44:37
Sure, we can have a separate frameQueue to publish
| |
90 }); | |
91 | |
92 dispatch_semaphore_wait(_frameSemaphore, DISPATCH_TIME_FOREVER); | |
93 } | |
94 } | |
95 [_reader cancelReading]; | |
96 _reader = nil; | |
97 }); | |
98 } | |
99 | |
100 - (void)stopCapture { | |
101 _capturerStopped = YES; | |
102 RTCLog(@"File capturer stopped."); | |
103 } | |
104 | |
105 #pragma mark - Private | |
106 | |
107 - (nullable NSString *)pathForFileName:(NSString *)fileName { | |
108 NSArray *nameComponents = [fileName componentsSeparatedByString:@"."]; | |
109 if (nameComponents.count != 2) { | |
110 return nil; | |
111 } | |
112 | |
113 NSString *path = | |
114 [[NSBundle mainBundle] pathForResource:nameComponents[0] ofType:nameCompon ents[1]]; | |
115 return path; | |
116 } | |
117 | |
118 - (dispatch_queue_t)frameQueue { | |
119 if (!_frameQueue) { | |
120 _frameQueue = dispatch_queue_create("org.webrtc.filecapturer.video", DISPATC H_QUEUE_SERIAL); | |
121 dispatch_set_target_queue(_frameQueue, | |
122 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_ BACKGROUND, 0)); | |
123 } | |
124 return _frameQueue; | |
125 } | |
126 | |
127 - (void)dealloc { | |
128 [self stopCapture]; | |
129 } | |
130 | |
131 @end | |
OLD | NEW |