objc2-av-foundation 0.3.2

Bindings to the AVFoundation framework
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
//! This file has been automatically generated by `objc2`'s `header-translator`.
//! DO NOT EDIT
use core::ffi::*;
use core::ptr::NonNull;
use objc2::__framework_prelude::*;
#[cfg(feature = "objc2-core-media")]
use objc2_core_media::*;
use objc2_foundation::*;
#[cfg(feature = "objc2-uniform-type-identifiers")]
use objc2_uniform_type_identifiers::*;

use crate::*;

/// These constants are returned by the AVAssetWriter status property to indicate whether it can successfully write samples to its output file.
///
///
/// Indicates that the status of the asset writer is not currently known.
///
/// Indicates that the asset writer is successfully writing samples to its output file.
///
/// Indicates that the asset writer has successfully written all samples following a call to finishWriting.
///
/// Indicates that the asset writer can no longer write samples to its output file because of an error. The error is described by the value of the asset writer's error property.
///
/// Indicates that the asset writer can no longer write samples because writing was canceled with the cancelWriting method.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/avfoundation/avassetwriterstatus?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct AVAssetWriterStatus(pub NSInteger);
impl AVAssetWriterStatus {
    #[doc(alias = "AVAssetWriterStatusUnknown")]
    pub const Unknown: Self = Self(0);
    #[doc(alias = "AVAssetWriterStatusWriting")]
    pub const Writing: Self = Self(1);
    #[doc(alias = "AVAssetWriterStatusCompleted")]
    pub const Completed: Self = Self(2);
    #[doc(alias = "AVAssetWriterStatusFailed")]
    pub const Failed: Self = Self(3);
    #[doc(alias = "AVAssetWriterStatusCancelled")]
    pub const Cancelled: Self = Self(4);
}

unsafe impl Encode for AVAssetWriterStatus {
    const ENCODING: Encoding = NSInteger::ENCODING;
}

unsafe impl RefEncode for AVAssetWriterStatus {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

extern_class!(
    /// AVAssetWriter provides services for writing media data to a new file,
    ///
    ///
    /// Instances of AVAssetWriter can write media to new files in formats such as the QuickTime movie file format or the MPEG-4 file format. AVAssetWriter has support for automatic interleaving of media data for multiple concurrent tracks. Source media data can be obtained from instances of AVAssetReader for one or more assets or from other sources outside of AVFoundation.
    ///
    /// Instances of AVAssetWriter can re-encode media samples as they are written. Instances of AVAssetWriter can also optionally write metadata collections to the output file.
    ///
    /// A single instance of AVAssetWriter can be used once to write to a single file. Clients that wish to write to files multiple times must use a new instance of AVAssetWriter each time.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfoundation/avassetwriter?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct AVAssetWriter;
);

extern_conformance!(
    unsafe impl NSObjectProtocol for AVAssetWriter {}
);

impl AVAssetWriter {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;

        #[cfg(feature = "AVMediaFormat")]
        /// Returns an instance of AVAssetWriter configured to write to a file in a specified container format.
        ///
        ///
        /// Parameter `URL`: The location of the file to be written. The URL must be a file URL.
        ///
        /// Parameter `fileType`: A UTI indicating the format of the file to be written.
        ///
        /// Parameter `outError`: On return, if initialization of the AVAssetWriter fails, points to an NSError describing the nature of the failure.
        ///
        /// Returns: An instance of AVAssetWriter.
        ///
        ///
        /// Writing will fail if a file already exists at the specified URL.
        ///
        /// UTIs for container formats that can be written are declared in AVMediaFormat.h.
        #[unsafe(method(assetWriterWithURL:fileType:error:_))]
        #[unsafe(method_family = none)]
        pub unsafe fn assetWriterWithURL_fileType_error(
            output_url: &NSURL,
            output_file_type: &AVFileType,
        ) -> Result<Retained<Self>, Retained<NSError>>;

        #[cfg(feature = "AVMediaFormat")]
        /// Creates an instance of AVAssetWriter configured to write to a file in a specified container format.
        ///
        ///
        /// Parameter `URL`: The location of the file to be written. The URL must be a file URL.
        ///
        /// Parameter `fileType`: A UTI indicating the format of the file to be written.
        ///
        /// Parameter `outError`: On return, if initialization of the AVAssetWriter fails, points to an NSError describing the nature of the failure.
        ///
        /// Returns: An instance of AVAssetWriter.
        ///
        ///
        /// Writing will fail if a file already exists at the specified URL.
        ///
        /// This method throws an exception if the output file type is not declared in AVMediaFormat.h.
        #[unsafe(method(initWithURL:fileType:error:_))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithURL_fileType_error(
            this: Allocated<Self>,
            output_url: &NSURL,
            output_file_type: &AVFileType,
        ) -> Result<Retained<Self>, Retained<NSError>>;

        #[cfg(feature = "objc2-uniform-type-identifiers")]
        /// Creates an instance of AVAssetWriter configured to output segment data in a specified container format.
        ///
        ///
        /// Parameter `outputContentType`: A UTType indicating the format of the segment data to be output.
        ///
        /// Returns: An instance of AVAssetWriter.
        ///
        ///
        /// Clients that want to receive segment data through the -assetWriter:didOutputSegmentData:segmentType:segmentReport: or -assetWriter:didOutputSegmentData:segmentType: delegate method should use this initializer instead of -initWithURL:fileType:error:.
        ///
        /// Clients may use +typeWithIdentifier: with a UTI to create an instance of UTType. See
        /// <UniformTypeIdentifiers
        /// /UTType.h>.
        ///
        /// This method throws an exception if the output content type UTI for container format is not declared in AVMediaFormat.h.
        #[unsafe(method(initWithContentType:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithContentType(
            this: Allocated<Self>,
            output_content_type: &UTType,
        ) -> Retained<Self>;

        /// The location of the file for which the instance of AVAssetWriter was initialized for writing.
        ///
        /// You may use [[UTType typeWithIdentifier:outputFileType] preferredFilenameExtension] to obtain an appropriate path extension for the outputFileType you have specified. For more information, see
        /// <UniformTypeIdentifiers
        /// /UTType.h>.
        #[unsafe(method(outputURL))]
        #[unsafe(method_family = none)]
        pub unsafe fn outputURL(&self) -> Retained<NSURL>;

        #[cfg(feature = "AVMediaFormat")]
        /// The UTI of the file format of the file for which the instance of AVAssetWriter was initialized for writing.
        #[unsafe(method(outputFileType))]
        #[unsafe(method_family = none)]
        pub unsafe fn outputFileType(&self) -> Retained<AVFileType>;

        #[cfg(feature = "AVMediaFormat")]
        /// The media types for which inputs can be added to the receiver.
        ///
        ///
        /// Some media types may not be accepted within the file format with which an AVAssetWriter was initialized.
        #[unsafe(method(availableMediaTypes))]
        #[unsafe(method_family = none)]
        pub unsafe fn availableMediaTypes(&self) -> Retained<NSArray<AVMediaType>>;

        /// The status of writing samples to the receiver's output file.
        ///
        ///
        /// The value of this property is an AVAssetWriterStatus that indicates whether writing is in progress, has completed successfully, has been canceled, or has failed. Clients of AVAssetWriterInput objects should check the value of this property after appending samples fails to determine why no more samples could be written. This property is thread safe.
        #[unsafe(method(status))]
        #[unsafe(method_family = none)]
        pub unsafe fn status(&self) -> AVAssetWriterStatus;

        /// If the receiver's status is AVAssetWriterStatusFailed, this describes the error that caused the failure.
        ///
        ///
        /// The value of this property is an NSError that describes what caused the receiver to no longer be able to write to its output file. If the receiver's status is not AVAssetWriterStatusFailed, the value of this property is nil. This property is thread safe.
        #[unsafe(method(error))]
        #[unsafe(method_family = none)]
        pub unsafe fn error(&self) -> Option<Retained<NSError>>;

        #[cfg(feature = "AVMetadataItem")]
        /// A collection of metadata to be written to the receiver's output file.
        ///
        ///
        /// The value of this property is an array of AVMetadataItem objects representing the collection of top-level metadata to be written in the output file.
        ///
        /// This property cannot be set after writing has started.
        #[unsafe(method(metadata))]
        #[unsafe(method_family = none)]
        pub unsafe fn metadata(&self) -> Retained<NSArray<AVMetadataItem>>;

        #[cfg(feature = "AVMetadataItem")]
        /// Setter for [`metadata`][Self::metadata].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setMetadata:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setMetadata(&self, metadata: &NSArray<AVMetadataItem>);

        /// Specifies whether the output file should be written in way that makes it more suitable for playback over a network
        ///
        ///
        /// When the value of this property is YES, the output file will be written in such a way that playback can start after only a small amount of the file is downloaded.
        ///
        /// This property cannot be set after writing has started.
        #[unsafe(method(shouldOptimizeForNetworkUse))]
        #[unsafe(method_family = none)]
        pub unsafe fn shouldOptimizeForNetworkUse(&self) -> bool;

        /// Setter for [`shouldOptimizeForNetworkUse`][Self::shouldOptimizeForNetworkUse].
        #[unsafe(method(setShouldOptimizeForNetworkUse:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setShouldOptimizeForNetworkUse(&self, should_optimize_for_network_use: bool);

        /// Specifies a directory that is suitable for containing temporary files generated during the process of writing an asset.
        ///
        ///
        /// AVAssetWriter may need to write temporary files when configured in certain ways, such as when performsMultiPassEncodingIfSupported is set to YES on one or more of its inputs.  This property can be used to control where in the filesystem those temporary files are created.  All temporary files will be deleted when asset writing is completed, is canceled, or fails.
        ///
        /// When the value of this property is nil, the asset writer will choose a suitable location when writing temporary files.  The default value is nil.
        ///
        /// This property cannot be set after writing has started.  The asset writer will fail if a file cannot be created in this directory (for example, due to insufficient permissions).
        #[unsafe(method(directoryForTemporaryFiles))]
        #[unsafe(method_family = none)]
        pub unsafe fn directoryForTemporaryFiles(&self) -> Option<Retained<NSURL>>;

        /// Setter for [`directoryForTemporaryFiles`][Self::directoryForTemporaryFiles].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setDirectoryForTemporaryFiles:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setDirectoryForTemporaryFiles(
            &self,
            directory_for_temporary_files: Option<&NSURL>,
        );

        #[cfg(feature = "AVAssetWriterInput")]
        /// The inputs from which the asset writer receives media data.
        ///
        /// The value of this property is an NSArray containing concrete instances of AVAssetWriterInput. Inputs can be added to the receiver using the addInput: method.
        #[unsafe(method(inputs))]
        #[unsafe(method_family = none)]
        pub unsafe fn inputs(&self) -> Retained<NSArray<AVAssetWriterInput>>;

        #[cfg(feature = "AVMediaFormat")]
        /// Tests whether output settings for a specific media type are supported by the receiver's file format.
        ///
        ///
        /// Parameter `outputSettings`: The output settings that are to be tested.
        ///
        /// Parameter `mediaType`: The media type for which the output settings are to be tested. Media types are defined in AVMediaFormat.h.
        ///
        /// Returns: A BOOL indicating whether the given output settings can be used for the given media type.
        ///
        ///
        /// This method determines whether the output settings for the specified media type can be used with the receiver's file format. For example, video compression settings that specify H.264 compression are not compatible with file formats that cannot contain H.264-compressed video.
        ///
        /// Attempting to add an input with output settings and a media type for which this method returns NO will cause an exception to be thrown.
        ///
        /// # Safety
        ///
        /// `output_settings` generic should be of the correct type.
        #[unsafe(method(canApplyOutputSettings:forMediaType:))]
        #[unsafe(method_family = none)]
        pub unsafe fn canApplyOutputSettings_forMediaType(
            &self,
            output_settings: Option<&NSDictionary<NSString, AnyObject>>,
            media_type: &AVMediaType,
        ) -> bool;

        #[cfg(feature = "AVAssetWriterInput")]
        /// Tests whether an input can be added to the receiver.
        ///
        ///
        /// Parameter `input`: The AVAssetWriterInput object to be tested.
        ///
        /// Returns: A BOOL indicating whether the input can be added to the receiver.
        ///
        ///
        /// An input that accepts media data of a type that is not compatible with the receiver, or with output settings that are not compatible with the receiver, cannot be added.
        #[unsafe(method(canAddInput:))]
        #[unsafe(method_family = none)]
        pub unsafe fn canAddInput(&self, input: &AVAssetWriterInput) -> bool;

        #[cfg(feature = "AVAssetWriterInput")]
        /// Adds an input to the receiver.
        ///
        ///
        /// Parameter `input`: The AVAssetWriterInput object to be added.
        ///
        ///
        /// Inputs are created with a media type and output settings. These both must be compatible with the receiver.
        ///
        /// Inputs cannot be added after writing has started.
        ///
        /// This method throws an exception if any of the following conditions are satisfied:
        /// - the input's media type is not allowed for this asset writer
        /// - writing uncompressed video in a specific format
        /// - passthrough* to files (other than AVFileTypeQuickTimeMovie) is missing a format hint in the AVAssetWriterInput initializer
        /// - passthrough* is not supported for this media/file type combination (for example, AVFileTypeWAVE only supports AVMediaTypeAudio)
        ///
        /// Passthrough is indicated when the input's output settings are nil.
        #[unsafe(method(addInput:))]
        #[unsafe(method_family = none)]
        pub unsafe fn addInput(&self, input: &AVAssetWriterInput);

        /// Prepares the receiver for accepting input and for writing its output to its output file.
        ///
        ///
        /// Returns: A BOOL indicating whether writing successfully started.
        ///
        ///
        /// This method must be called after all inputs have been added and other configuration properties have been set in order to tell the receiver to prepare for writing. After this method is called, clients can start writing sessions using startSessionAtSourceTime: and can write media samples using the methods provided by each of the receiver's inputs.
        ///
        /// If writing cannot be started, this method returns NO. Clients can check the values of the status and error properties for more information on why writing could not be started.
        ///
        /// On iOS, if the status of an AVAssetWriter is AVAssetWriterStatusWriting when the client app goes into the background, its status will change to AVAssetWriterStatusFailed and appending to any of its inputs will fail.  You may want to use -[UIApplication beginBackgroundTaskWithExpirationHandler:] to avoid being interrupted in the middle of a writing session and to finish writing the data that has already been appended.  For more information about executing code in the background, see the iOS Application Programming Guide.
        #[unsafe(method(startWriting))]
        #[unsafe(method_family = none)]
        pub unsafe fn startWriting(&self) -> bool;

        #[cfg(feature = "objc2-core-media")]
        /// Initiates a sample-writing session for the receiver.
        ///
        ///
        /// Parameter `startTime`: The starting asset time for the sample-writing session, in the timeline of the source samples.
        ///
        ///
        /// Sequences of sample data appended to the asset writer inputs are considered to fall within "sample-writing sessions", initiated with this method. Accordingly, this method must be called after writing has started (using -startWriting) but before any sample data is appended to the receiver's inputs.
        ///
        /// Each writing session has a start time which, where allowed by the file format being written, defines the mapping from the timeline of source samples to the timeline of the written file. In the case of the QuickTime movie file format, the first session begins at movie time 0, so a sample appended with timestamp T will be played at movie time (T-startTime).  Samples with timestamps earlier than startTime will still be added to the output file but will be edited out (i.e. not presented during playback). If the earliest appended sample for an input has a timestamp later than than startTime, an empty edit will be inserted to preserve synchronization between tracks of the output asset.
        ///
        /// To end the session started by use of this method, use -endSessionAtSourceTime: or -finishWritingWithCompletionHandler:.  It is an error to invoke -startSessionAtSourceTime: twice in a row without invoking -endSessionAtSourceTime: in between.
        ///
        /// NOTE: Multiple sample-writing sessions are currently not supported. It is an error to call -startSessionAtSourceTime: a second time after calling -endSessionAtSourceTime:.
        #[unsafe(method(startSessionAtSourceTime:))]
        #[unsafe(method_family = none)]
        pub unsafe fn startSessionAtSourceTime(&self, start_time: CMTime);

        #[cfg(feature = "objc2-core-media")]
        /// Concludes a sample-writing session.
        ///
        ///
        /// Parameter `endTime`: The ending asset time for the sample-writing session, in the timeline of the source samples.
        ///
        ///
        /// Call this method to complete a session started with -startSessionAtSourceTime:.
        ///
        /// The endTime defines the moment on the timeline of source samples at which the session ends. In the case of the QuickTime movie file format, each sample-writing session's startTime...endTime pair corresponds to a period of movie time into which the session's samples are inserted. Samples with timestamps that are later than the session end time will still be added to the written file but will be edited out (i.e. not presented during playback). So if the first session has duration D1 = endTime - startTime, it will be inserted into the written file at time 0 through D1; the second session would be inserted into the written file at time D1 through D1+D2, etc. It is legal to have a session with no samples; this will cause creation of an empty edit of the prescribed duration.
        ///
        /// It is not mandatory to call -endSessionAtSourceTime:; if -finishWritingWithCompletionHandler: is called without first invoking -endSessionAtSourceTime:, the session's effective end time will be the latest end timestamp of the session's appended samples (i.e. no samples will be edited out at the end).
        ///
        /// It is an error to append samples outside of a sample-writing session.  To append more samples after invoking -endSessionAtSourceTime:, you must first start a new session using -startSessionAtSourceTime:.
        ///
        /// NOTE: Multiple sample-writing sessions are currently not supported. It is an error to call -startSessionAtSourceTime: a second time after calling -endSessionAtSourceTime:.
        ///
        /// This method throws an exception if the session is ended without first starting it.
        #[unsafe(method(endSessionAtSourceTime:))]
        #[unsafe(method_family = none)]
        pub unsafe fn endSessionAtSourceTime(&self, end_time: CMTime);

        /// Cancels the creation of the output file.
        ///
        ///
        /// If the status of the receiver is "failed" or "completed," -cancelWriting is a no-op.  Otherwise, this method will block until writing is canceled.
        ///
        /// If an output file was created by the receiver during the writing process, -cancelWriting will delete the file.
        ///
        /// This method should not be called concurrently with -[AVAssetWriterInput appendSampleBuffer:] or -[AVAssetWriterInputPixelBufferAdaptor appendPixelBuffer:withPresentationTime:].
        #[unsafe(method(cancelWriting))]
        #[unsafe(method_family = none)]
        pub unsafe fn cancelWriting(&self);

        /// Completes the writing of the output file.
        ///
        ///
        /// Returns: A BOOL indicating whether writing successfully finished.
        ///
        ///
        /// This method is deprecated.  Use finishWritingWithCompletionHandler: instead.
        ///
        /// This method will block until writing is finished. When this method returns successfully, the file being written by the receiver is complete and ready to use.
        ///
        /// Because this method is blocking and can take a long time to execute (especially with shouldOptimizeForNetworkUse set to YES), it should not be called from the main thread.  Doing so can cause the finishWriting operation to fail.
        ///
        /// If writing cannot be finished, this method returns NO. Clients can check the values of the status and error properties for more information on why writing could not be finished.
        ///
        /// This method should not be called concurrently with -[AVAssetWriterInput appendSampleBuffer:] or -[AVAssetWriterInputPixelBufferAdaptor appendPixelBuffer:withPresentationTime:].
        #[deprecated]
        #[unsafe(method(finishWriting))]
        #[unsafe(method_family = none)]
        pub unsafe fn finishWriting(&self) -> bool;

        #[cfg(feature = "block2")]
        /// Marks all unfinished inputs as finished and completes the writing of the output file.
        ///
        ///
        /// This method returns immediately and causes its work to be performed asynchronously.
        ///
        /// When the writing of the output file is finished, or if a failure or a cancellation occurs in the meantime, the specified handler will be invoked to indicate completion of the operation. To determine whether the operation succeeded, your handler can check the value of AVAssetWriter.status. If the status is AVAssetWriterStatusFailed, AVAsset.error will contain an instance of NSError that describes the failure.
        ///
        /// To guarantee that all sample buffers are successfully written, ensure all calls to -[AVAssetWriterInput appendSampleBuffer:] or -[AVAssetWriterInputPixelBufferAdaptor appendPixelBuffer:withPresentationTime:] have returned before invoking this method.
        ///
        /// # Safety
        ///
        /// `handler` block must be sendable.
        #[unsafe(method(finishWritingWithCompletionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn finishWritingWithCompletionHandler(
            &self,
            handler: &block2::DynBlock<dyn Fn()>,
        );
    );
}

/// AVAssetWriterFileTypeSpecificProperties.
impl AVAssetWriter {
    extern_methods!(
        #[cfg(feature = "objc2-core-media")]
        /// For file types that support movie fragments, specifies the frequency at which movie fragments should be written.
        ///
        ///
        /// When movie fragments are used, a partially written asset whose writing is unexpectedly interrupted can be successfully opened and played up to multiples of the specified time interval. The default value of this property is kCMTimeInvalid, which indicates that movie fragments should not be used.
        ///
        /// When using movie fragments, for best writing performance to external storage devices, set the movieFragmentInterval to 10 seconds or greater.
        ///
        /// This property cannot be set after writing has started.
        #[unsafe(method(movieFragmentInterval))]
        #[unsafe(method_family = none)]
        pub unsafe fn movieFragmentInterval(&self) -> CMTime;

        #[cfg(feature = "objc2-core-media")]
        /// Setter for [`movieFragmentInterval`][Self::movieFragmentInterval].
        #[unsafe(method(setMovieFragmentInterval:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setMovieFragmentInterval(&self, movie_fragment_interval: CMTime);

        #[cfg(feature = "objc2-core-media")]
        /// For file types that support movie fragments, specifies the interval at which initial movie fragment should be written.
        ///
        ///
        /// This property is irrelevant if the movieFragmentInterval property is not set. The default value is kCMTimeInvalid, which indicates that the interval for initial movie fragment is same as the one specified by movieFragmentInterval property.
        ///
        /// This property cannot be set after writing has started.
        #[unsafe(method(initialMovieFragmentInterval))]
        #[unsafe(method_family = none)]
        pub unsafe fn initialMovieFragmentInterval(&self) -> CMTime;

        #[cfg(feature = "objc2-core-media")]
        /// Setter for [`initialMovieFragmentInterval`][Self::initialMovieFragmentInterval].
        #[unsafe(method(setInitialMovieFragmentInterval:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setInitialMovieFragmentInterval(
            &self,
            initial_movie_fragment_interval: CMTime,
        );

        /// For file types that support movie fragments, specifies the initial movie fragment sequence number.
        ///
        ///
        /// The value must be equal to or greater than 1.
        ///
        /// The default value is 1.
        ///
        /// Note that if you combine movie fragments produced by an instance of AVAssetWriter with additional movie fragments, produced either by a different instance of AVAssetWriter or by some other means, it is necessary to ensure that movie fragment sequence numbers increase monotonically across the entire combined collection, in temporal order.
        ///
        /// This property cannot be set after writing has started.
        #[unsafe(method(initialMovieFragmentSequenceNumber))]
        #[unsafe(method_family = none)]
        pub unsafe fn initialMovieFragmentSequenceNumber(&self) -> NSInteger;

        /// Setter for [`initialMovieFragmentSequenceNumber`][Self::initialMovieFragmentSequenceNumber].
        #[unsafe(method(setInitialMovieFragmentSequenceNumber:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setInitialMovieFragmentSequenceNumber(
            &self,
            initial_movie_fragment_sequence_number: NSInteger,
        );

        /// For file types that support fragmented MPEG-4, specifies whether the movie fragments should be produced in way that makes them suitable for combining with movie fragments produced by one or more other instances of AVAssetWriter into a single fragment stream of uniform encoding.
        ///
        ///
        /// The default value is NO.
        ///
        /// When multiple instances of AVAssetWriter are used to produce distinct streams that complement each other, for example to create HLS encoding or bitrate variants, it’s not necessary to set this property to YES.
        ///
        /// This property cannot be set after writing has started.
        #[unsafe(method(producesCombinableFragments))]
        #[unsafe(method_family = none)]
        pub unsafe fn producesCombinableFragments(&self) -> bool;

        /// Setter for [`producesCombinableFragments`][Self::producesCombinableFragments].
        #[unsafe(method(setProducesCombinableFragments:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setProducesCombinableFragments(&self, produces_combinable_fragments: bool);

        #[cfg(feature = "objc2-core-media")]
        /// For file types that support movie fragments, provides a hint of the final duration of the file to be written
        ///
        ///
        /// The value of this property must be a nonnegative, numeric CMTime.  Alternatively, if the value of this property is an invalid CMTime (e.g. kCMTimeInvalid), no overall duration hint will be written to the file.  The default value is kCMTimeInvalid.
        ///
        /// This property is currently ignored if movie fragments are not being written.  Use the movieFragmentInterval property to enable movie fragments.
        ///
        /// This property cannot be set after writing has started.
        #[unsafe(method(overallDurationHint))]
        #[unsafe(method_family = none)]
        pub unsafe fn overallDurationHint(&self) -> CMTime;

        #[cfg(feature = "objc2-core-media")]
        /// Setter for [`overallDurationHint`][Self::overallDurationHint].
        #[unsafe(method(setOverallDurationHint:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setOverallDurationHint(&self, overall_duration_hint: CMTime);

        #[cfg(feature = "objc2-core-media")]
        /// For file types that contain a 'moov' atom, such as QuickTime Movie files, specifies the asset-level time scale to be used.
        ///
        ///
        /// The default value is 0, which indicates that the receiver should choose a convenient value, if applicable.
        ///
        /// This property cannot be set after writing has started.
        #[unsafe(method(movieTimeScale))]
        #[unsafe(method_family = none)]
        pub unsafe fn movieTimeScale(&self) -> CMTimeScale;

        #[cfg(feature = "objc2-core-media")]
        /// Setter for [`movieTimeScale`][Self::movieTimeScale].
        #[unsafe(method(setMovieTimeScale:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setMovieTimeScale(&self, movie_time_scale: CMTimeScale);
    );
}

/// AVAssetWriterInputGroups.
impl AVAssetWriter {
    extern_methods!(
        #[cfg(feature = "AVMediaSelectionGroup")]
        /// Tests whether an input group can be added to the receiver.
        ///
        ///
        /// Parameter `inputGroup`: The AVAssetWriterInputGroup object to be tested.
        ///
        /// Returns: A BOOL indicating whether the input group can be added to the receiver.
        ///
        ///
        /// If outputFileType specifies a container format that does not support mutually exclusive relationships among tracks, or if the specified instance of AVAssetWriterInputGroup contains inputs with media types that cannot be related, the group cannot be added to the AVAssetWriter.
        ///
        /// This method throws an exception if any of the following conditions are satisfied:
        /// - this writer's output file type does not support mutually exclusive relationships among tracks (allowed types are AVFileTypeQuickTimeMovie, AVFileTypeAppleM4A, AVFileTypeAppleM4V, AVFileType3GPP, AVFileTypeMPEG4)
        /// - any AVAssetWriterInput in the input group is also present in an input group already added
        #[unsafe(method(canAddInputGroup:))]
        #[unsafe(method_family = none)]
        pub unsafe fn canAddInputGroup(&self, input_group: &AVAssetWriterInputGroup) -> bool;

        #[cfg(feature = "AVMediaSelectionGroup")]
        #[unsafe(method(addInputGroup:))]
        #[unsafe(method_family = none)]
        pub unsafe fn addInputGroup(&self, input_group: &AVAssetWriterInputGroup);

        #[cfg(feature = "AVMediaSelectionGroup")]
        /// The instances of AVAssetWriterInputGroup that have been added to the AVAssetWriter.
        ///
        ///
        /// The value of this property is an NSArray containing concrete instances of AVAssetWriterInputGroup.  Input groups can be added to the receiver using the addInputGroup: method.
        #[unsafe(method(inputGroups))]
        #[unsafe(method_family = none)]
        pub unsafe fn inputGroups(&self) -> Retained<NSArray<AVAssetWriterInputGroup>>;
    );
}

extern_class!(
    /// [Apple's documentation](https://developer.apple.com/documentation/avfoundation/avassetwriterinputgroup?language=objc)
    #[unsafe(super(AVMediaSelectionGroup, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    #[cfg(feature = "AVMediaSelectionGroup")]
    pub struct AVAssetWriterInputGroup;
);

#[cfg(feature = "AVMediaSelectionGroup")]
extern_conformance!(
    unsafe impl NSCopying for AVAssetWriterInputGroup {}
);

#[cfg(feature = "AVMediaSelectionGroup")]
unsafe impl CopyingHelper for AVAssetWriterInputGroup {
    type Result = Self;
}

#[cfg(feature = "AVMediaSelectionGroup")]
extern_conformance!(
    unsafe impl NSObjectProtocol for AVAssetWriterInputGroup {}
);

#[cfg(feature = "AVMediaSelectionGroup")]
impl AVAssetWriterInputGroup {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;

        #[cfg(feature = "AVAssetWriterInput")]
        #[unsafe(method(assetWriterInputGroupWithInputs:defaultInput:))]
        #[unsafe(method_family = none)]
        pub unsafe fn assetWriterInputGroupWithInputs_defaultInput(
            inputs: &NSArray<AVAssetWriterInput>,
            default_input: Option<&AVAssetWriterInput>,
        ) -> Retained<Self>;

        #[cfg(feature = "AVAssetWriterInput")]
        #[unsafe(method(initWithInputs:defaultInput:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithInputs_defaultInput(
            this: Allocated<Self>,
            inputs: &NSArray<AVAssetWriterInput>,
            default_input: Option<&AVAssetWriterInput>,
        ) -> Retained<Self>;

        #[cfg(feature = "AVAssetWriterInput")]
        /// The inputs grouped together by the receiver.
        ///
        ///
        /// The value of this property is an NSArray containing concrete instances of AVAssetWriterInput.
        #[unsafe(method(inputs))]
        #[unsafe(method_family = none)]
        pub unsafe fn inputs(&self) -> Retained<NSArray<AVAssetWriterInput>>;

        #[cfg(feature = "AVAssetWriterInput")]
        /// The input designated at the defaultInput of the receiver.
        ///
        ///
        /// The value of this property is a concrete instance of AVAssetWriterInput.
        #[unsafe(method(defaultInput))]
        #[unsafe(method_family = none)]
        pub unsafe fn defaultInput(&self) -> Option<Retained<AVAssetWriterInput>>;
    );
}

/// AVAssetWriterSegmentation.
impl AVAssetWriter {
    extern_methods!(
        #[cfg(feature = "objc2-core-media")]
        /// Specifies preferred segment interval.
        ///
        ///
        /// The default value is kCMTimeInvalid, which means that the receiver will choose an appropriate default value. The value can be set to positive numeric or kCMTimeIndefinite.
        /// If the value is kCMTimeIndefinite, every time a client calls -flushSegment the receiver outputs a segment data.
        ///
        /// This property cannot be set after writing has started.
        #[unsafe(method(preferredOutputSegmentInterval))]
        #[unsafe(method_family = none)]
        pub unsafe fn preferredOutputSegmentInterval(&self) -> CMTime;

        #[cfg(feature = "objc2-core-media")]
        /// Setter for [`preferredOutputSegmentInterval`][Self::preferredOutputSegmentInterval].
        #[unsafe(method(setPreferredOutputSegmentInterval:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setPreferredOutputSegmentInterval(
            &self,
            preferred_output_segment_interval: CMTime,
        );

        #[cfg(feature = "objc2-core-media")]
        /// Specifies start time of initial segment.
        ///
        ///
        /// A numeric time must be set if the value of preferredOutputSegmentInterval property is positive numeric. If not, this property is irrelevant.
        ///
        /// This property cannot be set after writing has started.
        #[unsafe(method(initialSegmentStartTime))]
        #[unsafe(method_family = none)]
        pub unsafe fn initialSegmentStartTime(&self) -> CMTime;

        #[cfg(feature = "objc2-core-media")]
        /// Setter for [`initialSegmentStartTime`][Self::initialSegmentStartTime].
        #[unsafe(method(setInitialSegmentStartTime:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setInitialSegmentStartTime(&self, initial_segment_start_time: CMTime);

        #[cfg(feature = "AVMediaFormat")]
        /// Specifies a file type profile for the specified file type.
        ///
        ///
        /// The default value is nil, which means that the receiver will choose an appropriate default profile based on the specified file type.
        ///
        /// Clients that want to receive segment data that is suitable for streaming through the -assetWriter:didOutputSegmentData:segmentType:segmentReport: or -assetWriter:didOutputSegmentData:segmentType: delegate method should set AVFileTypeProfileMPEG4AppleHLS, or AVFileTypeProfileMPEG4CMAFCompliant to require output that is specifically compliant with CMAF format, with AVFileTypeMPEG4 file type.
        ///
        /// File type profiles are declared in AVMediaFormat.h.
        ///
        /// This property cannot be set after writing has started.
        #[unsafe(method(outputFileTypeProfile))]
        #[unsafe(method_family = none)]
        pub unsafe fn outputFileTypeProfile(&self) -> Option<Retained<AVFileTypeProfile>>;

        #[cfg(feature = "AVMediaFormat")]
        /// Setter for [`outputFileTypeProfile`][Self::outputFileTypeProfile].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setOutputFileTypeProfile:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setOutputFileTypeProfile(
            &self,
            output_file_type_profile: Option<&AVFileTypeProfile>,
        );

        /// An object that implements one or more of the methods in the AVAssetWriterDelegate protocol.
        ///
        ///
        /// This property cannot be set after writing has started.
        #[unsafe(method(delegate))]
        #[unsafe(method_family = none)]
        pub unsafe fn delegate(
            &self,
        ) -> Option<Retained<ProtocolObject<dyn AVAssetWriterDelegate>>>;

        /// Setter for [`delegate`][Self::delegate].
        ///
        /// This is a [weak property][objc2::topics::weak_property].
        #[unsafe(method(setDelegate:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setDelegate(
            &self,
            delegate: Option<&ProtocolObject<dyn AVAssetWriterDelegate>>,
        );

        /// Closes the current segment and outputs it to the -assetWriter:didOutputSegmentData:segmentType:segmentReport: or -assetWriter:didOutputSegmentData:segmentType: delegate method.
        ///
        ///
        /// This method throws an exception if the delegate method to output segment data is not implemented, or if the value of the preferredOutputSegmentInterval property is not kCMTimeIndefinite.
        #[unsafe(method(flushSegment))]
        #[unsafe(method_family = none)]
        pub unsafe fn flushSegment(&self);
    );
}

extern_protocol!(
    /// [Apple's documentation](https://developer.apple.com/documentation/avfoundation/avassetwriterdelegate?language=objc)
    pub unsafe trait AVAssetWriterDelegate: NSObjectProtocol + Send + Sync {
        #[cfg(feature = "AVAssetSegmentReport")]
        /// A method invoked when a segment data is output.
        ///
        ///
        /// Parameter `writer`: An AVAssetWriter instance.
        ///
        /// Parameter `segmentData`: An instance of NSData containing a segment data.
        ///
        /// Parameter `segmentType`: A segment type of the segment data. Segment types are declared in AVAssetSegmentReport.h.
        ///
        /// Parameter `segmentReport`: An AVAssetSegmentReport instance.
        ///
        ///
        /// If this method is implemented, normal file writing will be suppressed. The instance of AVAssetWriter must be initialized by -initWithContentType: initializer.
        /// Then, clients append media data to AVAssetWriterInputs added to the receiver, call -markAsFinished for each input to mark the input as finished and call -finishWritingWithCompletionHandler: to finish writing as is the case in normal file writing.
        ///
        /// Do not use the movieFragmentInterval or shouldOptimizeForNetworkUse properties, as these properties are ignored in this mode of operation.
        ///
        /// Clients that need to reference the NSData outside of the scope of this method must retain or copy it and then release it when they are finished with it.
        ///
        /// The segmentReport provides information on the segment data. If there is no information available to report, the segmentReport may be nil.
        /// Clients that do not need information on consecutive segment data should implement the -assetWriter:didOutputSegmentData:segmentType: method instead of this one for greater efficiency, as this will signal the receiver to skip the preparation of segment reports.
        /// See more detailed description of AVAssetSegmentReport in AVAssetSegmentReport.h.
        ///
        /// If the file type is AVFileTypeMPEG4 and the outputFileTypeProfile is AVFileTypeProfileMPEG4AppleHLS or AVFileTypeProfileMPEG4CMAFCompliant, when the segmentType is AVAssetSegmentTypeInitialization, the segment contains a 'moov' atom that does not contain any sample tables other than the sample descriptions, and is suitable for use as an initialization segment for the following segment data sequences.
        /// When the segmentType is AVAssetSegmentTypeSeparable, the segment contains a 'moof' atom  that contains one 'moof' atom followed by one 'mdat' atom.
        ///
        /// 1. If the value of preferredOutputSegmentInterval property is positive numeric, when (a sample's output PTS - InitialSegmentStartTime) >= (interval * N) (N = 1, 2, 3...), the receiver waits for next sync sample and outputs a segment data that includes all samples appended since the previous interval to the delegate method when the sync sample appears, so that the next segment can start with the sync sample.
        /// In this configuration, passthrough (by passing nil to output settings for AVAssetWriterInputs) and compression are available. The media type of input can be AVMediaTypeVideo or AVMediaTypeAudio.
        /// Only one input of each media type can be added for compression and when (a sample's PTS - InitialSegmentStartTime) >= (interval * N) (N = 1, 2, 3...), the sample will be forced to be encoded as sync sample so that the current segment will be closed immediately.
        /// For passthrough, only one input can be added.
        ///
        /// 2. If the value of preferredOutputSegmentInterval property is kCMTimeIndefinite, every time a client calls -flushSegment the receiver outputs a segment data that includes all samples appended since the previous call to the delegate method.
        /// The delegate method may be called asynchronously, on a different thread from the one that calls -flushSegment.
        /// In this configuration, only passthrough is available. The media type of input can be AVMediaTypeVideo or AVMediaTypeAudio.
        /// Only one input of each media type can be added.
        /// The client should call -flushSegment prior to a sync sample so that the next segment can start with the sync sample. Otherwise, it is an error.
        #[optional]
        #[unsafe(method(assetWriter:didOutputSegmentData:segmentType:segmentReport:))]
        #[unsafe(method_family = none)]
        unsafe fn assetWriter_didOutputSegmentData_segmentType_segmentReport(
            &self,
            writer: &AVAssetWriter,
            segment_data: &NSData,
            segment_type: AVAssetSegmentType,
            segment_report: Option<&AVAssetSegmentReport>,
        );

        #[cfg(feature = "AVAssetSegmentReport")]
        /// A method invoked when a segment data is output.
        ///
        ///
        /// Parameter `writer`: An AVAssetWriter instance.
        ///
        /// Parameter `segmentData`: An instance of NSData containing a segment data.
        ///
        /// Parameter `segmentType`: A segment type of the segment data. Segment types are declared in AVAssetSegmentReport.h.
        ///
        ///
        /// The usage of this method is same as -assetWriter:didOutputSegmentData:segmentType:segmentReport: except that this method does not deliver AVAssetSegmentReport.
        ///
        /// If clients implement the -assetWriter:didOutputSegmentData:segmentType:segmentReport: method, that method is called instead of this one.
        #[optional]
        #[unsafe(method(assetWriter:didOutputSegmentData:segmentType:))]
        #[unsafe(method_family = none)]
        unsafe fn assetWriter_didOutputSegmentData_segmentType(
            &self,
            writer: &AVAssetWriter,
            segment_data: &NSData,
            segment_type: AVAssetSegmentType,
        );
    }
);