AVCaptureMovieFileOutput won't call delegate in StartRecordingToOutputFile

bradmbradm AUMember ✭✭✭
edited January 2016 in Xamarin.iOS

I am having more issues with the AVCaptureMovieFileOutput class, but this time in iOS. I am trying to record from the screen and save to a file. I setup my AVCaptureMovieFileOutput, being sure to set its MovieFragmentInterval to CMTime.Invalid as I hear it can sometimes cause recording issues if you don't. I have not changed any of its other properties.

I have a button on screen which calls StopRecording() on my AVCaptureMovieFileOutput object which then in tern should trigger the delegate from the StartRecordingToOutputFile call which I called earlier. This second delegate however gets called on and off randomly. Sometimes I may have 10 times in a row where it is called, and 10 times in a row where it is not, and then toggle between working and not working. Between each of these runs I hit stop and start from Xamarin Studio so it launches a new instance of the app.

My first thought was that my output file already existed,

string tempFile = "Recording-" + DateTime.Now.ToString("yyyy-M-d--HH-mm-ss") + ".mp4";`

but this is how I declare my variable for my output file. It's directory is also randomly generated, so unless two GUID's match and also tempFile was created in the same second I don't think its happening. Example output path is like this.

/var/mobile/Containers/Data/Application/AF8EE11D-3DF6-4C09-B0FB-115E0803AEF7/Documents/../Library/Caches/01ab119d-f840-47c8-9717-b8680b8eb139/videoCache/Recording-2016-1-5--17-23-05.mp4

"/var/mobile/Containers/Data/Application/AF8EE11D-3DF6-4C09-B0FB-115E0803AEF7/Documents/../Library/Caches/" was generated from

var documents = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments);
return Path.Combine (documents, "..", "Library", "Caches");

But I don't believe it to be part of the issue because of how intermittent it is.

I had noticed that the Recording property of the AVCaptureMovieFileOutput was set to true briefly after I had called StopRecording. I have not tested if it is still true when recording does get saved, only had tested and know its true when it was not saved. I had made this silly little loop in the mean time, but I get the same results with and without all the additional faf. I however do know that regardless if the delegate is called or not, the "end stop recording" is called and it is always stopped, so I know at this point in the code that Recording has indeed been set to false.

ThreadPool.QueueUserWorkItem(delegate{
    do
    {
        if (_movieFileOutput.Recording)
        {
            Debug.WriteLine("still recording");
            _movieFileOutput.StopRecording();
            Thread.Sleep(500);
        }
        else
        {
            Debug.WriteLine("ayyyy finished recording");
        }
    }
    while (_movieFileOutput.Recording);
    Debug.WriteLine("end stop recording" + (_movieFileOutput.Recording ? "recording" : "stopped"));

});

For the delegates in the StartRecordingToOutputFile method I had tried 4 different things which did not seem to change anything.
1 - Used anonymous delegates (at least I believe this is what they are called).

_movieFileOutput.StartRecordingToOutputFile(outputFile, delegate(NSObject[] connections) {
// Is called
}, delegate(NSObject[] connections, NSError error) {
// Is sometimes never called.
});

2 - Moved these anonymous delegates to be their own functions.
3 - Made my class inherit from IAVCaptureFileOutputRecordingDelegate and add the required methods and passed through this as the argument.
4 - Subclassed AVCaptureFileOutputRecordingDelegate called FileOutputRecordingDelegate and passed it through as the parameter.

All 4 methods don't seem to have any change in result.

Opening up xcode devices and watching the console does not output any info different if it does or does not work.

I added a File.Exist above and below the above do/while code block to check if this specific file exists or not. In both cases the file exists in both before and after code block executes.

So aside from putting my "yay we recorded a video, now lets continue" code after my do/while loop above and ignoring any calls going to the delegates I don't know how to proceed. Any suggestions on what to do or how to debug this further would be greatly appreciated.

Posts

  • bradmbradm AUMember ✭✭✭

    I moved my _movieFileOutput initialization code from the camera initialization area to the area where StartRecordingToOutputFile gets called (had to put it in between BeginConfiguration and CommitConfiguration calls of the AVCaptureSession. So far seems to do the trick but I have been burned by solutions before.

  • bradmbradm AUMember ✭✭✭

    As it turns out, _movieFileObject was missing a bunch of properties (moving the code to a new project).
    I had to add this linker.xml file to the project.
    <?xml version="1.0" encoding="UTF-8" ?> <linker> <assembly fullname="Xamarin.iOS"> <namespace fullname="AVFoundation" /> </assembly> </linker>

    And then added

    --xml=linker.xml

    to the Additional mtouch arguments in the iOS Build properties of the app.

  • MagneticLlamaMagneticLlama USMember ✭✭
    edited September 2017

    I am experiencing the same issue. I'm attempting to implement your final comment relating to the linker.xml file. I'm unable to do this because iOS is not listing LinkDescription as a valid Build Action, despite the Xamarin documentation instructing me to use this option.
    https://developer.xamarin.com/guides/cross-platform/advanced/custom_linking/

Sign In or Register to comment.