Is it possible to play videos using a subclass of NSURLProtocol using MPMovieController or AVFoundation?

I'm currently trying to play the video at a URL that has a custom schema defined in a custom subclass of NSURLProtocol. Initially, I used MPMoviePlayerController in an attempt to accomplish this, but after running into problems and checking, I found that MPMoviePlayerController did not handle NSURLProtocol subclasses as expected.

How to play movie with url using custom NSURLProtocol?

As a result, I decided to look at the structure of AVFoundation, however, it seems that this also does not work. I just wanted to know if this is possible, or am I trying to get through walls?

Using AVFoundation, the approach I'm using is shown below. It is probably worth mentioning that this works when using the standard URL for videos posted on the Internet, but does not work with custom NSURLProtocol.

// this doesn't work //AVPlayer *player = [[AVPlayer alloc] initWithURL:[NSURL urlWithString:@"custom URL scheme"]]; // this works AVPlayer *player = [[AVPlayer alloc] initWithURL:[NSURL urlWithString:@"some url to video on remote server"]]; AVPlayerLayer *layer = [AVAVPlayerLayer playerLayerWithPlayer:player]; // configure the layer [self.view.layer addSublayer:layer]; [player play]; 

Is there anything else that would have to be done to play from a specific subclass of NSURLProtocol?

+4
ios avfoundation mpmovieplayercontroller avplayer nsurlprotocol
source share
1 answer

I recently managed to get NSURLProtocol to work with MPMoviePlayerController. This is mostly useful because MPMoviePlayerController accepts only NSURL, so it did not skip cookies or headers (for authentication). Using NSURLProtocol allowed. I thought that one day I would share some code for the community.

Basically, using NSURLProtocol, we can intercept the connection between MPMoviePlayerController and the streaming request, add cookies on this path or possibly keep the stream offline or replace it with cat ect video ... To do this, you need to create a new class My extension NSURLProtocol :

MyURLProtocol.h:

 #import <Foundation/Foundation.h> @interface MyURLProtocol : NSURLProtocol + (void) register; + (void) injectURL:(NSString*) urlString cookie:(NSString*)cookie; @end 

MyURLProtocol.m:

 #import "MyURLProtocol.h" @interface MyURLProtocol() <NSURLConnectionDelegate> { NSMutableURLRequest* myRequest; NSURLConnection * connection; } @end static NSString* injectedURL = nil; static NSString* myCookie = nil; @implementation MyURLProtocol // register the class to intercept all HTTP calls + (void) register { [NSURLProtocol registerClass:[self class]]; } // public static function to call when injecting a cookie + (void) injectURL:(NSString*) urlString cookie:(NSString*)cookie { injectedURL = urlString; myCookie = cookie; } // decide whether or not the call should be intercepted + (BOOL)canInitWithRequest:(NSURLRequest *)request { if([[[request allHTTPHeaderFields] objectForKey:@"BANANA"] isEqualToString:@"DELICIOUS"]) { return NO; } return [[[request URL] absoluteString] isEqualToString:injectedURL]; } // required (don't know what this means) + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { return request; } // intercept the request and handle it yourself - (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id<NSURLProtocolClient>)client { if (self = [super initWithRequest:request cachedResponse:cachedResponse client:client]) { myRequest = request.mutableCopy; [myRequest setValue:@"DELICIOUS" forHTTPHeaderField:@"BANANA"]; // add your own signature to the request } return self; } // load the request - (void)startLoading { // inject your cookie [myRequest setValue:myCookie forHTTPHeaderField:@"Cookie"]; connection = [[NSURLConnection alloc] initWithRequest:myRequest delegate:self]; } // overload didReceive data - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [[self client] URLProtocol:self didLoadData:data]; } // overload didReceiveResponse - (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse *)response { [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:[myRequest cachePolicy]]; } // overload didFinishLoading - (void)connectionDidFinishLoading:(NSURLConnection *)connection { [[self client] URLProtocolDidFinishLoading:self]; } // overload didFail - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { [[self client] URLProtocol:self didFailWithError:error]; } // handle load cancelation - (void)stopLoading { [connection cancel]; } @end 

using:

 [MyURLProtocol register]; [MyURLProtocol injectURL:@"http://server/your-video-url.mp4" cookie:@"mycookie=123"]; MPMoviePlayerController* moviePlayer = [[MPMoviePlayerController alloc]initWithContentURL:@"http://server/your-video-url.mp4"]; [moviePlayer play]; 
+5
source share

All Articles