Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2971c85
Pause/resume video recording for Android
huulbaek Mar 21, 2019
3e87cac
Specify type
bparrishMines Aug 1, 2019
d99f9d0
Merge branch 'master' of github.com:flutter/plugins into huulbaek/pau…
bparrishMines Aug 1, 2019
474604d
Merge branch 'master' of github.com:flutter/plugins into huulbaek/pau…
bparrishMines Aug 5, 2019
423adcd
Add pausing and resuming to example app
bparrishMines Aug 6, 2019
0214093
iOS side of pausing/resuming
bparrishMines Aug 6, 2019
7216d4a
Merge branch 'master' of github.com:flutter/plugins into huulbaek/pau…
bparrishMines Aug 7, 2019
113cd55
More documentation
bparrishMines Aug 7, 2019
5664547
Version bump
bparrishMines Aug 7, 2019
9210c26
Merge branch 'master' of github.com:flutter/plugins into huulbaek/pau…
bparrishMines Aug 12, 2019
3f47c60
Add video pausing and resuming
bparrishMines Aug 14, 2019
5baee78
get pausing and recording to work for no audio
bparrishMines Aug 15, 2019
da26df1
It works
bparrishMines Aug 16, 2019
b56d1fb
Merge branch 'pauseresume' of github.com:huulbaek/plugins into huulba…
bparrishMines Aug 16, 2019
542ee3d
Formatting
bparrishMines Aug 16, 2019
5023773
Add test for pausing and resuming
bparrishMines Aug 19, 2019
6dbbf8d
Merge branch 'master' into pauseresume
bparrishMines Aug 19, 2019
ca47f38
Call success outside try catch block
bparrishMines Aug 19, 2019
c758b26
formatting
bparrishMines Aug 19, 2019
70e1b13
Merge branch 'pauseresume' of github.com:huulbaek/plugins into huulba…
bparrishMines Aug 19, 2019
8ff306f
Disable audio in test and call result on iOS
bparrishMines Aug 19, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
get pausing and recording to work for no audio
  • Loading branch information
bparrishMines committed Aug 15, 2019
commit 5baee78a4da7b77b6a2774e2c625d01a5617dac3
108 changes: 65 additions & 43 deletions packages/camera/ios/Classes/CameraPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,17 @@ @interface FLTCam : NSObject <FlutterTexture,
@property(strong, nonatomic) AVCaptureAudioDataOutput *audioOutput;
@property(assign, nonatomic) BOOL isRecording;
@property(assign, nonatomic) BOOL isRecordingPaused;
@property(assign, nonatomic) BOOL recordingIsDiconnected;
@property(assign, nonatomic) BOOL videoIsDiconnected;
@property(assign, nonatomic) BOOL audioIsDiconnected;
@property(assign, nonatomic) BOOL isAudioSetup;
@property(assign, nonatomic) BOOL isStreamingImages;
@property(assign, nonatomic) ResolutionPreset resolutionPreset;
@property(assign, nonatomic) CMTime lastVideoSampleTime;
@property(assign, nonatomic) CMTime lastAudioSampleTime;
@property(assign, nonatomic) CMTime timeOffset;
@property(assign, nonatomic) CMTime videoTimeOffset;
@property(assign, nonatomic) CMTime audioTimeOffset;
@property(nonatomic) CMMotionManager *motionManager;
@property AVAssetWriterInputPixelBufferAdaptor *videoAdaptor;
- (instancetype)initWithCameraName:(NSString *)cameraName
resolutionPreset:(NSString *)resolutionPreset
enableAudio:(BOOL)enableAudio
Expand Down Expand Up @@ -426,59 +429,70 @@ - (void)captureOutput:(AVCaptureOutput *)output
});
return;
}
if (_recordingIsDiconnected) {
if (output == _captureVideoOutput) return;
_recordingIsDiconnected = NO;

CMTime timestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
if (_lastAudioSampleTime.flags & kCMTimeFlags_Valid) {
if (_timeOffset.flags & kCMTimeFlags_Valid) {
timestamp = CMTimeSubtract(timestamp, _timeOffset);
}
CMTime offset = CMTimeSubtract(timestamp, _lastAudioSampleTime);

// this stops us having to set a scale for _timeOffset before we see the first video time
if (_timeOffset.value == 0) {
_timeOffset = offset;
CFRetain(sampleBuffer);
CMTime currentSampleTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
CMTime dur = CMSampleBufferGetDuration(sampleBuffer);

if (_videoWriter.status != AVAssetWriterStatusWriting) {
[_videoWriter startWriting];
[_videoWriter startSessionAtSourceTime:currentSampleTime];
}

if (output == _captureVideoOutput) {
if (_videoIsDiconnected) {
_videoIsDiconnected = NO;

if (_videoTimeOffset.value == 0) {
_videoTimeOffset = CMTimeSubtract(currentSampleTime, _lastVideoSampleTime);
} else {
_timeOffset = CMTimeAdd(_timeOffset, offset);
CMTime adjustedSampleTime = CMTimeSubtract(currentSampleTime, _videoTimeOffset);
CMTime offset = CMTimeSubtract(adjustedSampleTime, _lastVideoSampleTime);
_videoTimeOffset = CMTimeAdd(_videoTimeOffset, offset);
}
}
_lastVideoSampleTime.flags = 0;
_lastAudioSampleTime.flags = 0;
}

CFRetain(sampleBuffer);
if (dur.value > 0) {
_lastVideoSampleTime = CMTimeAdd(currentSampleTime, dur);
} else {
_lastVideoSampleTime = currentSampleTime;
}

if (_timeOffset.value > 0) {
CFRelease(sampleBuffer);
sampleBuffer = [self adjustTime:sampleBuffer by:_timeOffset];
}
CVPixelBufferRef nextBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CMTime nextSampleTime = CMTimeSubtract(_lastVideoSampleTime, _videoTimeOffset);
[_videoAdaptor appendPixelBuffer:nextBuffer withPresentationTime:nextSampleTime];
} else {
if (_audioIsDiconnected) {
_audioIsDiconnected = NO;

CMTime lastSampleTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
CMTime dur = CMSampleBufferGetDuration(sampleBuffer);
if (_audioTimeOffset.value == 0) {
_audioTimeOffset = CMTimeSubtract(currentSampleTime, _lastAudioSampleTime);
} else {
CMTime adjustedSampleTime = CMTimeSubtract(currentSampleTime, _audioTimeOffset);
CMTime offset = CMTimeSubtract(adjustedSampleTime, _lastAudioSampleTime);
_audioTimeOffset = CMTimeAdd(_audioTimeOffset, offset);
}
}

if (output == _captureVideoOutput) {
_lastVideoSampleTime = CMTimeAdd(lastSampleTime, dur);
} else {
_lastAudioSampleTime = CMTimeAdd(lastSampleTime, dur);
}
if (dur.value > 0) {
_lastAudioSampleTime = CMTimeAdd(currentSampleTime, dur);
} else {
_lastAudioSampleTime = currentSampleTime;
}

if (_audioTimeOffset.value != 0) {
CFRelease(sampleBuffer);
sampleBuffer = [self adjustTime:sampleBuffer by:_audioTimeOffset];
}

if (_videoWriter.status != AVAssetWriterStatusWriting) {
[_videoWriter startWriting];
[_videoWriter startSessionAtSourceTime:lastSampleTime];
}
if (output == _captureVideoOutput) {
[self newVideoSample:sampleBuffer];
} else if (output == _audioOutput) {
[self newAudioSample:sampleBuffer];
}

CFRelease(sampleBuffer);
}
}

- (CMSampleBufferRef) adjustTime:(CMSampleBufferRef) sample by:(CMTime) offset
{
- (CMSampleBufferRef) adjustTime:(CMSampleBufferRef) sample by:(CMTime) offset {
CMItemCount count;
CMSampleBufferGetSampleTimingInfoArray(sample, 0, nil, &count);
CMSampleTimingInfo* pInfo = malloc(sizeof(CMSampleTimingInfo) * count);
Expand Down Expand Up @@ -582,8 +596,10 @@ - (void)startVideoRecordingAtPath:(NSString *)path result:(FlutterResult)result
}
_isRecording = YES;
_isRecordingPaused = NO;
_timeOffset = CMTimeMake(0, 0);
_recordingIsDiconnected = NO;
_videoTimeOffset = CMTimeMake(0, 1);
_audioTimeOffset = CMTimeMake(0, 1);
_videoIsDiconnected = NO;
_audioIsDiconnected = NO;
result(nil);
} else {
_eventSink(@{@"event" : @"error", @"errorDescription" : @"Video is already recording!"});
Expand Down Expand Up @@ -616,7 +632,8 @@ - (void)stopVideoRecordingWithResult:(FlutterResult)result {

- (void)pauseVideoRecording {
_isRecordingPaused = YES;
_recordingIsDiconnected = YES;
_videoIsDiconnected = YES;
_audioIsDiconnected = YES;
}

- (void)resumeVideoRecording {
Expand Down Expand Up @@ -675,6 +692,11 @@ - (BOOL)setupWriterForPath:(NSString *)path {
nil];
_videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings];

_videoAdaptor = [AVAssetWriterInputPixelBufferAdaptor
assetWriterInputPixelBufferAdaptorWithAssetWriterInput:_videoWriterInput
sourcePixelBufferAttributes:@{(NSString *)kCVPixelBufferPixelFormatTypeKey : @(videoFormat)}];

NSParameterAssert(_videoWriterInput);
_videoWriterInput.expectsMediaDataInRealTime = YES;

Expand Down