1

我正在使用AVFoundation's AVCaptureSession来捕获视频,并且正在使用MPMoviePlayerController从服务器播放流式传输的 url(视频)。当我只捕获视频时AVCaptureSession没有问题。但是,当我尝试播放流式传输的 url(with MPMoviePlayerController) 以及一次捕获视频AVCaptureSession时,会出现问题,因为从AVCaptureSession停止捕获。

这就是我所做的:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication ]delegate]; 
    if([appDelegate isIpad] == YES)
    controlsView = [[UIView alloc] initWithFrame:CGRectMake(self.view.bounds.origin.x+200, self.view.bounds.origin.y+250, self.view.bounds.size.width, self.view.bounds.size.height)];
    else
     controlsView = [[UIView alloc] initWithFrame:self.view.bounds];
    controlsView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:controlsView];
    [self.view sendSubviewToBack:controlsView];

    //settingsBtn = [[UIButton alloc]initWithFrame:CGRectMake(10,400, 50, 50)];
    settingsBtn = [[UIButton alloc]initWithFrame:CGRectMake(10,400, 50, 50)];
    [settingsBtn setImage:[UIImage imageNamed:@"settings.png"] forState:UIControlStateNormal];
    [settingsBtn addTarget:self action:@selector(settingsAction) forControlEvents:UIControlEventTouchUpInside];
    [controlsView addSubview:settingsBtn];

    callButton = [[UIButton alloc]initWithFrame:CGRectMake(260,400, 50, 50)];

    if(isCallButtonClicked ==NO)
    [callButton setImage:[UIImage imageNamed:@"call.png"] forState:UIControlStateNormal];

    else
        [callButton setImage:[UIImage imageNamed:@"callEnd.png"] forState:UIControlStateNormal];
    [callButton addTarget:self action:@selector(callAction) forControlEvents:UIControlEventTouchUpInside];

    [controlsView addSubview:callButton];


    statusLabel = [[UILabel alloc]initWithFrame:CGRectMake(120, 20, 150, 40)];
    statusLabel.textColor = [UIColor whiteColor];
    statusLabel.backgroundColor = [UIColor clearColor];
    statusLabel.textAlignment = UITextAlignmentLeft;
    statusLabel.font = [UIFont boldSystemFontOfSize:20];

    dot1 = [[UIView alloc] initWithFrame:CGRectMake(75, 20, 7, 7)];
    dot1.layer.cornerRadius = 5;
    dot1.backgroundColor = [UIColor whiteColor];
    [statusLabel addSubview:dot1];

    dot2 = [[UIView alloc] initWithFrame:CGRectMake(84, 20, 7, 7)];
    dot2.layer.cornerRadius = 5;
    dot2.backgroundColor = [UIColor whiteColor];
    [statusLabel addSubview:dot2];

    dot3 = [[UIView alloc] initWithFrame:CGRectMake(93, 20, 7, 7)];
    dot3.layer.cornerRadius = 5;
    dot3.backgroundColor = [UIColor whiteColor];
    [statusLabel addSubview:dot3];

    downStreamView = [[UIView alloc]initWithFrame:CGRectMake(controlsView.bounds.origin.x, controlsView.bounds.origin.y, controlsView.bounds.size.width, controlsView.bounds.size.height - 70)];
    [[controlsView layer] addSublayer:downStreamView.layer];
    downStreamView.layer.backgroundColor = [UIColor greenColor].CGColor;

    AVCaptureSession *captureSession = [[AVCaptureSession alloc]init];
    NSError *error;

    /* getting the device input */

    AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:[self frontFacingCamera] error:&error];
    if(error)
    {
        NSLog(@"%@",@"Could not create video input");
    }

    [captureSession addInput:videoInput];


    AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:[self audioDevice] error:&error];
    [captureSession addInput:audioInput];
    audioOutput = [[AVCaptureAudioDataOutput alloc]init];
    [captureSession addOutput:audioOutput];


    previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:captureSession];
    [previewLayer setFrame:CGRectMake(controlsView.bounds.origin.x, controlsView.bounds.origin.y, controlsView.bounds.size.width, controlsView.bounds.size.height - 70)];
    [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];

    [[controlsView layer] addSublayer:previewLayer];

    [captureSession startRunning];
}

//make call Action
-(void)makeCallAction
{
    if(isCallButtonClicked == NO)
    {
        statusLabel.text = @"Dialling";
        [controlsView addSubview:statusLabel];
        if(!isAnimationStarted)
        [self animate];
        [callButton setImage:[UIImage imageNamed:@"callEnd.png"] forState:UIControlStateNormal];

        [UIView animateWithDuration:2.0
                         animations:^{ 

                             CGRect frame = CGRectMake(downStreamView.layer.bounds.origin.x, downStreamView.layer.bounds.size.height-100, 100, 100);
                             previewLayer.frame = frame;
                             [downStreamView.layer addSublayer:previewLayer];
                         }
                         completion:^(BOOL finished){
                             //Do nothing
                     }];

        isCallButtonClicked = YES;
    }
    else if(isCallButtonClicked == YES)
    {
        [statusLabel removeFromSuperview];
        [callButton setImage:[UIImage imageNamed:@"call.png"] forState:UIControlStateNormal];

        [UIView animateWithDuration:2.0
                         animations:^{ 
                             [previewLayer setFrame:CGRectMake(controlsView.bounds.origin.x, controlsView.bounds.origin.y, controlsView.bounds.size.width, controlsView.bounds.size.height - 70)];
                             [[controlsView layer] addSublayer:previewLayer];
                         } 
                         completion:^(BOOL finished){
                             //Do nothing
                         }];
        isCallButtonClicked = NO;
    }
}


//Settings Action

-(void)settingsAction
{
    NSString *nibName = nil;

    if ([[[UIDevice currentDevice] model] isEqualToString:@"iPhone"] || [[[UIDevice currentDevice] model] isEqualToString:@"iPhone Simulator"]) {
        nibName = @"SettingsViewController";
    }     
    else {
        nibName = @"SettingsViewController_iPad";
    }
    SettingsViewController *settingsController = [[SettingsViewController alloc]initWithNibName:nibName bundle:nil];

    [self.navigationController presentModalViewController:settingsController animated:YES];
}


-(void)callAction
{
    NSURL *theMovieURL = [NSURL URLWithString:@"someURL.m3u8"];
    if (theMovieURL)
    {
        if ([theMovieURL scheme])   // sanity check on the URL
        {
            /* Play the movie with the specified URL. */
            [self playStreamingURL:theMovieURL];
        }
    }
    [self makeCallAction];
}


-(void)playStreamingURL:(NSURL *)aUrlStr
{
    MPMovieSourceType movieSourceType = MPMovieSourceTypeUnknown;
    /* If we have a streaming url then specify the movie source type. */
    if ([[aUrlStr pathExtension] compare:@"m3u8" options:NSCaseInsensitiveSearch] == NSOrderedSame) 
    {
        movieSourceType = MPMovieSourceTypeStreaming;
    }
    [self createAndPlayMovieForURL:aUrlStr sourceType:movieSourceType];
}

-(void)createAndPlayMovieForURL:(NSURL *)movieURL sourceType:(MPMovieSourceType)sourceType
{
    [self createAndConfigurePlayerWithURL:movieURL sourceType:sourceType];

    /* making the player to be visible in full screen mode */
    //if(!self.moviePlayerController.fullscreen)
    //  self.moviePlayerController.fullscreen = YES;

    /* disabling the controls of the movie player */
    self.moviePlayerController.controlStyle = MPMovieControlStyleNone;

    /* Play the movie! */
    [[self moviePlayerController] play];
}

-(void)createAndConfigurePlayerWithURL:(NSURL *)movieURL sourceType:(MPMovieSourceType)sourceType 
{    
    [controlsView addSubview:downStreamView];

    /* Create a new movie player object. */
    MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];

    if (player) 
    {
        /* Save the movie object. */
        [self setMoviePlayerController:player];


        player.contentURL = MPMovieControlStyleNone;
        //if(!player.fullscreen)
        //  player.fullscreen = YES;

        /* Register the current object as an observer for the movie
         notifications. */
        // [self installMovieNotificationObservers];

        /* Specify the URL that points to the movie file. */
        [player setContentURL:movieURL];        

        /* If you specify the movie type before playing the movie it can result 
         in faster load times. */
        [player setMovieSourceType:sourceType];

        /* Apply the user movie preference settings to the movie player object. */
        //[self applyUserSettingsToMoviePlayer];

        /* Add a background view as a subview to hide our other view controls 
         underneath during movie playback. */

        //CGRect viewInsetRect = CGRectInset ([self.view bounds],
        // kMovieViewOffsetX,
        //kMovieViewOffsetY );
        /* Inset the movie frame in the parent view frame. */
        [[player view] setFrame:downStreamView.bounds];

        [player view].backgroundColor = [UIColor redColor];

        /* To present a movie in your application, incorporate the view contained 
         in a movie player’s view property into your application’s view hierarchy. 
         Be sure to size the frame correctly. */
        [downStreamView.layer addSublayer: [player view].layer];        
    }    
}

-(void)installMovieNotificationObservers
{
    MPMoviePlayerController *player = [self moviePlayerController];

    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(loadStateDidChange:) 
                                                  name:MPMoviePlayerLoadStateDidChangeNotification 
                                               object:player];

    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(moviePlayBackDidFinish:) 
                                                 name:MPMoviePlayerPlaybackDidFinishNotification 
                                               object:player];

    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(mediaIsPreparedToPlayDidChange:) 
                                                 name:MPMediaPlaybackIsPreparedToPlayDidChangeNotification 
                                               object:player];

    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(moviePlayBackStateDidChange:) 
                                                 name:MPMoviePlayerPlaybackStateDidChangeNotification 
                                               object:player];        
}



/*  Notification called when the movie finished playing. */
- (void) moviePlayBackDidFinish:(NSNotification*)notification
{
    NSNumber *reason = [[notification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey]; 
    switch ([reason integerValue]) 
    {
        /* The end of the movie was reached. */
        case MPMovieFinishReasonPlaybackEnded:
        /*
        Add your code here to handle MPMovieFinishReasonPlaybackEnded.
        */
        break;

        /* An error was encountered during playback. */
        case MPMovieFinishReasonPlaybackError:
        NSLog(@"An error was encountered during playback");
        [self performSelectorOnMainThread:@selector(displayError:) withObject:[[notification userInfo] objectForKey:@"error"] waitUntilDone:NO];
        [self removeMovieViewFromViewHierarchy];
        break;

        /* The user stopped playback. */
        case MPMovieFinishReasonUserExited:
        [self removeMovieViewFromViewHierarchy];
        break;

        default:
        break;
    }
}


/* Remove the movie view from the view hierarchy. */
-(void)removeMovieViewFromViewHierarchy
{
    MPMoviePlayerController *player = [self moviePlayerController];

    [player.view removeFromSuperview];
}


- (void)animate {

    isAnimationStarted = YES;

    //First Animation
    [UIView animateWithDuration:0.5 animations:^{

        dot1.alpha = 1;
        dot2.alpha = 0.5;
        dot3.alpha = 0.5;

        } completion:^(BOOL finished) {

            //2nd Animation
            [UIView animateWithDuration:0.5 animations:^{

                dot1.alpha = 0.5;
                dot2.alpha = 1;
                dot3.alpha = 0.5; 

                } completion:^(BOOL finished) {

                    //3rd Animation
                    [UIView animateWithDuration:0.5 animations:^{

                        dot1.alpha = 0.5;
                        dot2.alpha = 0.5;
                        dot3.alpha = 1;

                        } completion:^(BOOL finished) {

                            [self performSelector:@selector(animate)];
                            }];
                    }];           
            }];
}


// Find a camera with the specificed AVCaptureDevicePosition, returning nil if one is not found

- (AVCaptureDevice *) cameraWithPosition:(AVCaptureDevicePosition) position
{

    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];

    for (AVCaptureDevice *device in devices) {

        if ([device position] == position) {

            return device;

        }

    }

    return nil;

}

// Find a front facing camera, returning nil if one is not found

- (AVCaptureDevice *) frontFacingCamera
{
    return [self cameraWithPosition:AVCaptureDevicePositionFront];   
}


// Find a back facing camera, returning nil if one is not found

- (AVCaptureDevice *) backFacingCamera
{    
    return [self cameraWithPosition:AVCaptureDevicePositionBack];   
}

- (AVCaptureDevice *) audioDevice
{
    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
    if ([devices count] > 0) {

        return [devices objectAtIndex:0];
    }
    return nil;
}


-(void)audioData:(id)info
{
    NSArray *connections = audioOutput.connections;
    AVCaptureConnection *connection = [connections objectAtIndex:0];
    NSArray *audioChannels = connection.audioChannels;
    AVCaptureAudioChannel *audioChannel = [audioChannels objectAtIndex:0];
    //[label setText:[NSString stringWithFormat:@"%f", audioChannel.averagePowerLevel]];
}

伙计请帮我解决这个问题:(

问候

4

0 回答 0