Giter Club home page Giter Club logo

Comments (13)

moughxyz avatar moughxyz commented on September 28, 2024

Actually, I still get the occasional AVAudioSessionMediaServicesWereResetNotification notification. All I'm doing is:

    [_recorder openSession:^(NSError *sessionError, NSError *audioError, NSError *videoError, NSError *photoError) {

        SCRecordSession *session = [SCRecordSession recordSession];
        session.suggestedMaxRecordDuration = CMTimeMake(10, 1);
        _recorder.recordSession = session;
        session.videoSize = CGSizeMake(720, 1280);

        dispatch_async(dispatch_get_main_queue(), ^{       
            if (_recorder.isCaptureSessionOpened) {
                [_recorder startRunningSession:nil];
            }
        });
    }];

on viewDidLoad of my view controller. At this point, the camera does not display. This happens 1 out of 10 times, but I cannot replicate it consistently. It's a lot less frequent now that I've adjusted the capture session queue.

But there's still another issue:

- (void)dealloc {
    [self closeSession];
}

You can't dispatch_async in dealloc or you might get EXC_BAD_ACCESS exceptions. So we're forced to access the _captureSession on the main queue, which might be a problem.

from screcorder.

rFlex avatar rFlex commented on September 28, 2024

Hey Mo,

  • No need to dispatch in the main thread for openSession:
  • The startRunning is just made on the separate dispatch queue to avoid blocking the main thread.
  • closeSession is a sync method and does not do anything on a separate thread. It doesn't do any call to dispatch_async.
  • My implementation starts the capture session in the viewWillAppear. The example does it on the viewDidAppear. In both case, it works fine for me. Let me know if it still doesn't!
  • True about the error notifications, although I'm still waiting to experience an issue where I will have to make use of them. If you find an example of that I would be glad to hear it though.

Please let me know of how are going your research or if there is anything I can help you with.

from screcorder.

moughxyz avatar moughxyz commented on September 28, 2024

In any case, do you think it's safe to access the capture session from different queues?

from screcorder.

rFlex avatar rFlex commented on September 28, 2024

It's totally fine in this case, as soon as no modification are made in the
capture session while startRunning is being called.

You can definitely work with an object from different dispatch queues. It
becomes tricky when one thread attempts to modify a state from this object
while the same state is being read by another thread. This is not the case
here though, so we can totally avoid synchronising the operations on the
same dispatch queue.

On Saturday, May 3, 2014, Mo Bitar [email protected] wrote:

In any case, do you think it's safe to access the capture session from
different queues?


Reply to this email directly or view it on GitHubhttps://github.com//issues/30#issuecomment-42120773
.

from screcorder.

moughxyz avatar moughxyz commented on September 28, 2024

So you're saying it's ok because you, as the developer, know that you're not modifying the state of the object simultaneously on different queues. But, as a public project, it is not known how other people will use this, and they therefore may unintentionally access the object in a problematic way. Wouldn't it be the right thing to do is at least make it difficult to make developer mistakes? What would be the problem with always making sure you access the capture session on its respective queue?

Also, the queue is created as such:
_capture_queue = dispatch_queue_create("me.corsin.SCRecorder", NULL);

rather than
_capture_queue = dispatch_queue_create("me.corsin.SCRecorder", DISPATCH_QUEUE_SERIAL);

Which means that blocks you feed to the queue may be run concurrently rather than serially. Is this intended behavior?

from screcorder.

rFlex avatar rFlex commented on September 28, 2024
  • They can access the objects from whatever queues they want, it does not matter at all in this case. Why would I create a code that unnecessary synchronise an access to an object between multiple threads if it is not needed? This would be just be a waste of CPU time because of the mutex locking/unlocking operation needed and will also avoid the allocation of the obj-c block.
  • As the Apple documentation says, giving null as the attributes parameter will create a serial dispatch queue.

from screcorder.

moughxyz avatar moughxyz commented on September 28, 2024

Hmm. I'm trying to understand why this is ok. For example, you wouldn't be able to access a UIView object from any queue. Why is it ok to access an AVCaptureSession object from any queue?

from screcorder.

rFlex avatar rFlex commented on September 28, 2024

You can't access an UIView from a different queue because Apple just blocked it. It is a good thing that they do that because views objects are read and modified in a loop that runs in the main thread. They are also complexed objects and composed of mostly sub objects, arrays etc... Because of that, doing any operation on an UIView will almost never be done atomically. Each method call will involve various tests and conditions that will cause several CPU cycles, making this operation non-atomic. This will cause race conditions if this object is modified from several threads (abstracted as dispatch_queue on Cocoa). For those reasons Apple decided to block the access of the UIKit api from a different dispatch queue that the one who runs the main run loop.

In our case we have the AVCaptureSession that does not run in a loop, we have total control on how this object is modified because we are responsible to all the stuff that is gonna modify this object. Every modification is made on the thread in which the developer is using the SCRecorder, the only exception is the startRunning which run in a different dispatchQueue. From what I have seen modifying the AVCaptureSession while startRunning is being done does not seem to create any trouble, probably because the object uses locks with the beginConfiguration and commitConfiguration. The documentation says that using the two methods (which is what is being done in the SCRecorder) will commit the changes atomically, therefore explaining why it works on our case.

The only exception is if startRunning is called between a call of beginConfiguration and commitConfiguration. This will occur if the internal dispatchQueue in the SCRecorder didn't have enough time to process the block before beginConfiguration is called. Luckily this only happens if the developer changes some AVCaptureSession parameters in the SCRecorder right after he called startRunningSession:. This would be a silly implementation anyway because even if we added some dispatch_sync to synchronise the accesses, the main thread would be frozen for a few seconds in that case.

from screcorder.

moughxyz avatar moughxyz commented on September 28, 2024

Ah ok, very interesting. Thanks for the explanation.

I was getting a lot of AVAudioSessionMediaServicesWereResetNotification when trying to use the recorder, so I thought there must be some issue. So at first I thought it had something to do with queues. So I accessed the object only on the capture queue, and the issue went away.

But maybe it was just a coincidence. Will have to look into it deeper.

Thanks again.

from screcorder.

rFlex avatar rFlex commented on September 28, 2024

On your commits I see that you change the audio category between the startRunning and endRunning, can't it be something with that?

from screcorder.

moughxyz avatar moughxyz commented on September 28, 2024

No that was after.

The reason I did that was that if your phone is on silent mode, and a video is playing, and then you open the recorder and close it, the video audio no longer respects the silent mode and the audio is heard.

Configuring the audio session like that fixes the issue.

You might also want to look into adding video stabilization and smooth focus ability like I've added in my commits. Unless you didn't add those intentionally?

from screcorder.

rFlex avatar rFlex commented on September 28, 2024

Okay, I will investigate in my side and see if it happens for me too. Thanks for the feedback anyway.

I will definitely take a look, I never tried those features actually.

from screcorder.

rFlex avatar rFlex commented on September 28, 2024

Hey,

So after a few more testing a while ago I found out that modifying the AVCaptureSession while it is getting started makes the calling thread to block until the startRunningSession finishes. This should be a desirable behavior but the blocking takes way longer than what it should be.

For this reason I decided to remove the async feature on the startRunningSession:. It is now called "startRunningSession" and is synchronous. This let the possibility for the programmer to start the session on a separate thread but he will have to be sure that no SCRecorder modifications are made while the session is getting started. It can be done by disabling the UI that may interact with the SCRecorder for instance.

This should make it harder for the programmer to make mistakes ;).

from screcorder.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.