I need to implement video streaming service with http protocol. I know how to set url into MPMoviePlayerController, and how to set headerField into NSMutableURLRequest, but I have no idea how to combine them. I implement like below code, but not working, and I assume because there is no file info in the binary data.
- (void) openUrl
{
NSMutableURLRequest *reqURL = [NSMutableURLRequest requestWithURL:
[NSURL URLWithString:@"http://111.222.33.44/MOV/2013/4/123123123"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
[reqURL setHTTPMethod:@"GET"];
[reqURL setValue:@"Mozilla/4.0 (compatible;)" forHTTPHeaderField:@"User-Agent"];
[reqURL setValue:@"AAA-bb" forHTTPHeaderField:@"Auth-Token"];
[reqURL setValue:@"bytes=0-1024" forHTTPHeaderField:@"Range"];
[reqURL setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[NSURLConnection connectionWithRequest:reqURL delegate:self];
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(@"Received");
NSError * jsonERR = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"myMove.ts"];
[data writeToFile:path atomically:YES];
NSLog(@"copied");
NSURL *moveUrl = [NSURL fileURLWithPath:path];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc]init];
[player setContentURL:moveUrl];
player.view.frame = self.view.bounds;
player.controlStyle = MPMovieControlStyleEmbedded;
[self.view addSubview:player.view];
[player play];
}
I confirmed there is data in the delegate method, but I don't know how to play it. Please somebody let me know how to play it. Auth-Token and Range are necessary parameters.
Thanks.
It's true that Apple doesn't expose an easy way to inject headers into a MPMoviePlayerController's request. With a bit of effort, you can get this done using a custom NSURLProtocol. So, let's do it!
MyCustomURLProtocol.h:
@interface MyCustomURLProtocol : NSURLProtocol <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
@property (nonatomic, strong) NSURLConnection* connection;
@end
MyCustomURLProtocol.m:
@implementation MyCustomURLProtocol
// Define which protocols you want to handle
// In this case, I'm only handling "customProtocol" manually
// Everything else, (http, https, ftp, etc) is handled by the system
+ (BOOL) canInitWithRequest:(NSURLRequest *)request {
NSURL* theURL = request.URL;
NSString* scheme = theURL.scheme;
if([scheme isEqualToString:@"customProtocol"]) {
return YES;
}
return NO;
}
// You could modify the request here, but I'm doing my legwork in startLoading
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
return request;
}
// I'm not doing any custom cache work
+ (BOOL) requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
return [super requestIsCacheEquivalent:a toRequest:b];
}
// This is where I inject my header
// I take the handled request, add a header, and turn it back into http
// Then I fire it off
- (void) startLoading {
NSMutableURLRequest* mutableRequest = [self.request mutableCopy];
[mutableRequest setValue:@"customHeaderValue" forHTTPHeaderField:@"customHeaderField"];
NSURL* newUrl = [[NSURL alloc] initWithScheme:@"http" host:[mutableRequest.URL host] path:[mutableRequest.URL path]];
[mutableRequest setURL:newUrl];
self.connection = [NSURLConnection connectionWithRequest:mutableRequest delegate:self];
}
- (void) stopLoading {
[self.connection cancel];
}
// Below are boilerplate delegate implementations
// They are responsible for letting our client (the MPMovePlayerController) what happened
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[self.client URLProtocol:self didFailWithError:error];
self.connection = nil;
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.client URLProtocol:self didLoadData:data];
}
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
[self.client URLProtocolDidFinishLoading:self];
self.connection = nil;
}
@end
Before you can use your custom URL Protocol, you must register it. In your AppDelegate.m:
#import "MyCustomURLProtocol.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// ... Your normal setup ...
[NSURLProtocol registerClass:[MyCustomURLProtocol class]];
return YES;
}
Finally, you need to user your custom URL Protocol with the MPMediaPlayerController.
NSString* theURLString = [NSString stringWithFormat:@"customProtocol://%@%@", [_url host],[_url path]];
_player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:theURLString]];
The MPMoviePlayerController will now attempt to make the request with customProtocol:// instead of normal http://. Using this setup, we then intercept that request, add our headers, turn it into http, and then fire everything off.
Go back and read the documentation for NSURLConnection, and the URL-loading system in general. -connection:didReceiveData: is likely called more than once, as each chunk of the file arrives. You need to handle that, rather than assuming only the complete data arrives all at once.
来源:https://stackoverflow.com/questions/16027628/how-to-insert-header-info-into-mpmovieplayercontroller-url