通过iOS上的本地HTTP服务器播放HLS



>背景:我在服务器端有一个自定义身份验证机制,MPMoviePlayer不支持该机制。因此,我决定使用一个本地环回 HTTP 服务器,它将接收播放器的初始请求并提供 HLS 清单文件。

我处于播放器向我的本地 HTTP 服务器发起请求的位置,然后我的本地 HTTP 服务器从服务器获取清单文件并将其作为 http 响应写回播放器。但是MPMoviePlayer在那之后不会播放视频。

有人可以帮助我实现这一目标吗?

 #import "QumuMediaPlayerProxy.h"
#import "GZIP.h"

#define WELCOME_MSG  0
#define ECHO_MSG     1
#define WARNING_MSG  2

#define READ_TIMEOUT 15.0
#define READ_TIMEOUT_EXTENSION 10.0

@interface QumuMediaPlayerProxy()
@property NSURL *contentURL;

@end

@implementation QumuMediaPlayerProxy

+(NSURL*)getProxyURL{
    return [NSURL URLWithString:[NSString stringWithFormat:@"http://192.168.2.11:%d%@", SERVER_PORT, @"/nkm.do"]];
}
- (id)initWithURL:(NSURL*)contentURL
{
    if((self = [super init]))
    {

        socketQueue = dispatch_queue_create("socketQueue", NULL);

        listenSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:socketQueue];

        connectedSockets = [[NSMutableArray alloc] initWithCapacity:1];

        isRunning = NO;

        self.contentURL = contentURL;
    }
    return self;
}


- (void)startOnPort:(int)port
{
    if(!isRunning)
    {

        if (port < 0 || port > 65535)
        {
            port = 0;
        }

        NSError *error = nil;
        if(![listenSocket acceptOnPort:port error:&error])
        {
           NSLog(@"Error starting QumuMediaPlayerProxy: %@", error.debugDescription);
            return;
        }

        NSLog(@"QumuMediaPlayerProxy  started on port %hu", [listenSocket localPort]);
        isRunning = YES;

    }
}

-(void)stop
{
    if(isRunning)
    {
        // Stop accepting connections
        [listenSocket disconnect];

        // Stop any client connections
        @synchronized(connectedSockets)
        {
            NSUInteger i;
            for (i = 0; i < [connectedSockets count]; i++)
            {
                // Call disconnect on the socket,
                // which will invoke the socketDidDisconnect: method,
                // which will remove the socket from the list.
                [[connectedSockets objectAtIndex:i] disconnect];
            }
        }

        NSLog(@"Stopped QumuMediaPlayerProxy");
        isRunning = false;

    }

}

- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket
{
    // This method is executed on the socketQueue (not the main thread)

    @synchronized(connectedSockets)
    {
        [connectedSockets addObject:newSocket];
        NSLog(@"==Accepted client==");

    }

    [newSocket readDataWithTimeout:-1 tag:0];
}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    // This method is executed on the socketQueue (not the main thread)

    if (tag == ECHO_MSG)
    {
        [sock readDataToData:[GCDAsyncSocket CRLFData] withTimeout:READ_TIMEOUT tag:0];
    }
}

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    // This method is executed on the socketQueue (not the main thread)

    dispatch_async(dispatch_get_main_queue(), ^{
        @autoreleasepool {

            NSData *strData = [data subdataWithRange:NSMakeRange(0, [data length] - 2)];
            NSString *msg = [[NSString alloc] initWithData:strData encoding:NSUTF8StringEncoding];
            if (msg)
            {
                NSLog(@"msg===>%@",msg);
                NSLog(@"contentURL===>%@",self.contentURL.absoluteString);
                NSString *getStr = [msg componentsSeparatedByString:@"n"][0];
                NSString *requestedURL = [getStr substringWithRange:NSMakeRange(4, getStr.length-9)];
                //NSString *host = @"http://127.0.0.1:6910/";
                NSString *host = @"http://192.168.2.11:6910/";

                NSURL *requestURL = self.contentURL;
                if(![requestedURL containsString:@"nkm.do"]){
                    NSString *actualHost = [self.contentURL.absoluteString stringByReplacingOccurrencesOfString:self.contentURL.lastPathComponent withString:@""];

                    requestURL = [NSURL URLWithString:[actualHost stringByAppendingString:requestedURL]];
                }
                NSData *manifestData = [[QumuJSONHelper getInstance] fetchM3U8Playlist:requestURL];
                NSString *manifestStr = [[NSString alloc] initWithData:manifestData encoding:NSUTF8StringEncoding];
                NSLog(@"manifestStr===>%@",manifestStr);

             /*  NSArray *manifestArray = [manifestStr componentsSeparatedByString:@"n"];
                NSString *modifiedManifest = @"";
                for(int i=0;i<manifestArray.count;i++){
                    NSString *token = manifestArray[i];
                    if([token containsString:@"#EXT-X-STREAM-INF"]){
                        NSLog(@"== Found tag EXT-X-STREAM-INF ==");
                        modifiedManifest = [modifiedManifest stringByAppendingString:token];
                        modifiedManifest = [modifiedManifest stringByAppendingString:@"n"];

                        token = manifestArray[++i];
                       // token = [@"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_16x9/" stringByAppendingString:token];
                        token = [host stringByAppendingString:token];
                        NSLog(@"Modified URL===>%@",token);

                    }
                    modifiedManifest = [modifiedManifest stringByAppendingString:token];
                    modifiedManifest = [modifiedManifest stringByAppendingString:@"n"];

                }
                modifiedManifest = [modifiedManifest stringByReplacingOccurrencesOfString:@"URI="" withString:[NSString stringWithFormat:@"URI="%@",host]];
                NSLog(@"modifiedManifest===>%@",modifiedManifest);*/

                          NSString *response = @"HTTP/1.1 200 OK";

                response = [response stringByAppendingString:@"rnContent-Type: application/vnd.apple.mpegurl;charset=UTF-8"];
                 response = [response stringByAppendingFormat:@"rnContent-Length: %ld", (unsigned long)manifestData.length];
                 response = [response stringByAppendingString:@"rnConnection: keep-alive"];

                response = [response stringByAppendingString:@"rnrn"];


                NSLog(@"response header ===>%@",response);
                NSData *responseData = [response dataUsingEncoding:NSUTF8StringEncoding];
                [sock writeData:responseData withTimeout:-1 tag:0];
                [sock writeData:manifestData withTimeout:-1 tag:0];


            }
            else
            {
                NSLog(@"Error converting received data into UTF-8 String");
            }



        }
    });

    // Echo message back to client
    [sock writeData:data withTimeout:-1 tag:ECHO_MSG];
}

/**
 * This method is called if a read has timed out.
 * It allows us to optionally extend the timeout.
 * We use this method to issue a warning to the user prior to disconnecting them.
 **/
- (NSTimeInterval)socket:(GCDAsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag
                 elapsed:(NSTimeInterval)elapsed
               bytesDone:(NSUInteger)length
{
    if (elapsed <= READ_TIMEOUT)
    {
        NSString *warningMsg = @"Are you still there?rn";
        NSData *warningData = [warningMsg dataUsingEncoding:NSUTF8StringEncoding];

        [sock writeData:warningData withTimeout:-1 tag:WARNING_MSG];

        return READ_TIMEOUT_EXTENSION;
    }

    return 0.0;
}

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
    if (sock != listenSocket)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            @autoreleasepool {

                NSLog(@"Client Disconnected");

            }
        });

        @synchronized(connectedSockets)
        {
            [connectedSockets removeObject:sock];
        }
    }
}

-(void)dealloc{
   // [self stop];
}

@end

提前谢谢。

我正在将额外的回显消息写回服务器

  • void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag

一旦我删除它,一切都开始按预期工作。只是提到这一点,以防有人想使用上面发布的代码。

相关内容

  • 没有找到相关文章

最新更新