user1428156
user1428156

Reputation: 43

Delegate for AVCaptureVideoDataOutput and AVCaptureAudioDataOutput

I try to get CMSampleBufferRef from both AVCaptureVideoDataOutput and AVCaptureAudioDataOutput.

AVCamRecorder.h

#import <AVFoundation/AVFoundation.h>

@interface AVCamRecorder : NSObject {
}
    @property (nonatomic,retain) AVCaptureVideoDataOutput *videoDataOutput;
    @property (nonatomic,retain) AVCaptureAudioDataOutput *audioDataOutput;

@end

AVCamRecorder.m

#import "AVCamRecorder.h"
#import <AVFoundation/AVFoundation.h>

@interface AVCamRecorder (VideoDataOutputDelegate) <AVCaptureVideoDataOutputSampleBufferDelegate>
@end
@interface AVCamRecorder (AudioDataOutputDelegate) <AVCaptureAudioDataOutputSampleBufferDelegate>
@end


-(id)initWithSession:(AVCaptureSession *)aSession
{

    self = [super init];
    if (self != nil) {

        //AudioDataoutput
        AVCaptureAudioDataOutput *aAudioDataOutput =  [[AVCaptureAudioDataOutput alloc] init];

        //VideoDataoutput
        AVCaptureVideoDataOutput *aMovieDataOutput = [[AVCaptureVideoDataOutput alloc] init];


        if ([aSession canAddOutput:aAudioDataOutput]) {
            [aSession addOutput:aAudioDataOutput];
        }        
        if ([aSession canAddOutput:aMovieDataOutput]) {
        [aSession addOutput:aMovieDataOutput];
        }

        [aAudioDataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
        [aMovieDataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];

        [self setAudioDataOutput:aAudioDataOutput];
        [self setVideoDataOutput:aMovieDataOutput];

        [self setSession:aSession];

    }
    return self;
}

@implementation AVCamRecorder (VideoDataOutputDelegate)
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
       fromConnection:(AVCaptureConnection *)connection
{
    NSLog(@"VideoDataOutputDelegate = %@", captureOutput);
}    
@end

@implementation AVCamRecorder (AudioDataOutputDelegate)
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
       fromConnection:(AVCaptureConnection *)connection
{
    NSLog(@"AudioDataOutputDelegate = %@", captureOutput);
}
@end

Strangely, I got video data in the "@implementation AVCamRecorder (AudioDataOutputDelegate)"

AudioDataOutputDelegate = <AVCaptureVideoDataOutput: 0x208a7df0>

I switched the order of "@implementation AVCamRecorder (VideoDataOutputDelegate)" and "@implementation AVCamRecorder (VideoDataOutputDelegate)", and I got

VideoDataOutputDelegate = <AVCaptureVideoDataOutput: 0x208a7df0>

It seems that I cannot setup 2 "captureOutput:didOutputSampleBuffer:fromConnection:". Otherwise, the data comes into either one.

Or, did I make mistake setting up "@implementation AVCamRecorder (VideoDataOutputDelegate)" and "@implementation AVCamRecorder (AudioDataOutputDelegate)"?

I think I do not need to separate callback, but I am just wondering what is wrong.

Thank you for your help in advance.

Upvotes: 4

Views: 2206

Answers (1)

Martin R
Martin R

Reputation: 539745

You have defined 2 categories on the same class

AVCamRecorder (VideoDataOutputDelegate)
AVCamRecorder (AudioDataOutputDelegate)

declaring the same method

- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
       fromConnection:(AVCaptureConnection *)connection;

This results in undefined behavior. See Avoid Category Method Name Clashes in the "Programming with Objective-C" guide:

If the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime.
...

So your setup cannot work. You could instead

  • Define two separate classes, one as audio and one as video delegate,
  • define a single class category acting as audio + video delegate (and check in the callback method for which function it is called),
  • just use AVCamRecorder itself as audio + video delegate.

Upvotes: 1

Related Questions