Ronny vdb
Ronny vdb

Reputation: 2474

Load two AVPlayers with one video

I have two different views that are meant to play the same video, I am creating an app that will switch several times between the two views while the video is running.

I currently load the first view with the video as follows:

NSURL *url = [NSURL URLWithString:@"http://[URL TO VIDEO HERE]"];
AVURLAsset *avasset = [[AVURLAsset alloc] initWithURL:url options:nil];

AVPlayerItem *item = [[AVPlayerItem alloc] initWithAsset:avasset];
player = [[AVPlayer alloc] initWithPlayerItem:item];

playerLayer = [[AVPlayerLayer playerLayerWithPlayer:player] retain];
CGSize size = self.bounds.size;
float x = size.width/2.0-202.0;
float y = size.height/2.0 - 100;

//[player play];
playerLayer.frame = CGRectMake(x, y, 404, 200);
playerLayer.backgroundColor = [UIColor blackColor].CGColor;

[self.layer addSublayer:playerLayer];
NSString *tracksKey = @"tracks";

[avasset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:tracksKey] completionHandler:
 ^{
     dispatch_async(dispatch_get_main_queue(),
                    ^{
                        NSError *error = nil;
                        AVKeyValueStatus status = [avasset statusOfValueForKey:tracksKey error:&error];

                        if (status == AVKeyValueStatusLoaded) {

                            //videoInitialized = YES;
                            [player play];
                        }
                        else {
                            // You should deal with the error appropriately.
                            NSLog(@"The asset's tracks were not loaded:\n%@", [error localizedDescription]);
                        }
                    });
 }];

In my second view I want to load the video from the dispatch_get_main_queue so that the video in both views are in sync.

I was hoping someone could help me out with loading the data of the video from the first view into the second view.

Upvotes: 3

Views: 2009

Answers (3)

Fattie
Fattie

Reputation: 12621

For this ten year old question which has only ten year old answers which are out of date, here's the up to date answer.

var leadPlayer: AVPlayer ... the lead player you want to dupe

This does not work:

let leadPlayerItem: AVPlayerItem = leadPlayer.currentItem!
yourPlayer = AVPlayer(playerItem: leadPlayerItem)
yourPlayer.play()

Apple does not allow that (try it, see error).

This works. You must use the item:

let dupeItem: AVPlayerItem = AVPlayerItem(asset: leadPlayer.currentItem!.asset)
yourPlayer = AVPlayer(playerItem: dupeItem)
yourPlayer.play()

Fortunately it's now that easy.

Upvotes: 1

Nikita
Nikita

Reputation: 1853

It is very simple:

Init the first player:

AVAsset *asset = [AVAsset assetWithURL:URL];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];
AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];

And the second player in the same way, BUT, use the same asset from the first one. I have verified, it works.

There is all the info you need on the Apple page: https://developer.apple.com/library/mac/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/02_Playback.html

This abstraction means that you can play a given asset using different players simultaneously

this quote is from this page.

Upvotes: 6

MoDJ
MoDJ

Reputation: 4425

I don't think you will be able to get this approach to work. Videos are decoded in hardware and then the graphics buffer is sent to the graphics card. What you seem to want to do is decode a video in one view but then capture the contents of the first view and show it in a second view. That will not stay in sync because it would take time to capture the contents of the first window back into main memory and then those contents would need to be sent to the video card again. Basically, that is not going to work. You also cannot decode two h.264 videos streams and expect them to be in sync.

You could implement this with another approach entirely. If you decode the h.264 video to frames on disk (save each frame as a PNG) and then write your own loop that will decode the Nth PNG in a series of PNGs and then display the results in the two different windows. That will work fast enough to be an effective implementation on newer iPhone 4 and 5 and iPad 2 and 3. If you want to make use of a more advanced implementation, take a look at my AVAnimator library for iOS, you could get this approach working in 20 minutes if you use existing code.

Upvotes: 0

Related Questions