Как да се свържа с медиен сървър с помощта на протокол за поточно предаване в реално време (RTSP) от приложение за iOS?

Нов съм в програмирането на iOS и работя върху приложение за iPhone за заснемане на видео и предаване на живо през медиен сървър. Получих примерен код от тази връзка. Но този код прави iPhone като RTSP сървър и медийният сървър трябва да изтегли потока от iPhone. Въпреки че настоящата настройка работи добре, искам iPhone да изпрати потока на живо към медийния сървър, тъй като вярвам, че в реално време сървърът няма да се опитва да получи потока от всички потребители на iPhone. Връзката трябва да е друга, за да работи (поправете ме, ако греша). Моля, кажете ми какъв е правилният начин да направя това. Моля, кажете ми също коя рамка или вградени функции се предоставят от Apple, които могат да се използват за изпращане на потока на живо до сървър, което прави iPhone да работи като клиент и да инициира връзката.

Моля, проверете кода:

Заглавен файл

#import <Foundation/Foundation.h>
#import "RTSPServer.h"

@interface RTSPClientConnection : NSObject


+ (RTSPClientConnection*) createWithSocket:(CFSocketNativeHandle) s server:(RTSPServer*) server;

- (void) onVideoData:(NSArray*) data time:(double) pts;
- (void) shutdown;

@end

Файл за внедряване

#import "RTSPClientConnection.h"
#import "RTSPMessage.h"
#import "NALUnit.h"
#import "arpa/inet.h"

void tonet_short(uint8_t* p, unsigned short s)
{
//Code
}
void tonet_long(uint8_t* p, unsigned long l)
{
//Code
}

static const char* Base64Mapping = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const int max_packet_size = 1200;

NSString* encodeLong(unsigned long val, int nPad)
{
//Code
}

NSString* encodeToBase64(NSData* data)
{
//Code
}

enum ServerState
{
ServerIdle,
Setup,
Playing,
};

@interface RTSPClientConnection ()
{
CFSocketRef _s;
RTSPServer* _server;
CFRunLoopSourceRef _rls;

CFDataRef _addrRTP;
CFSocketRef _sRTP;
CFDataRef _addrRTCP;
CFSocketRef _sRTCP;
NSString* _session;
ServerState _state;
long _packets;
long _bytesSent;
long _ssrc;
BOOL _bFirst;

// time mapping using NTP
uint64_t _ntpBase;
uint64_t _rtpBase;
double _ptsBase;

// RTCP stats
long _packetsReported;
long _bytesReported;
NSDate* _sentRTCP;

// reader reports
CFSocketRef _recvRTCP;
CFRunLoopSourceRef _rlsRTCP;
}

- (RTSPClientConnection*) initWithSocket:(CFSocketNativeHandle) s Server:(RTSPServer*) server;
- (void) onSocketData:(CFDataRef)data;
- (void) onRTCP:(CFDataRef) data;

@end

static void onSocket (
           CFSocketRef s,
           CFSocketCallBackType callbackType,
           CFDataRef address,
           const void *data,
           void *info
           )
{
    RTSPClientConnection* conn = (__bridge RTSPClientConnection*)info;
    switch (callbackType)
    {
    case kCFSocketDataCallBack:
        [conn onSocketData:(CFDataRef) data];
        break;

    default:
        NSLog(@"unexpected socket event");
        break;
    }

}

static void onRTCP(CFSocketRef s,
               CFSocketCallBackType callbackType,
               CFDataRef address,
               const void *data,
               void *info
               )
{
    RTSPClientConnection* conn = (__bridge RTSPClientConnection*)info;
    switch (callbackType)
    {
    case kCFSocketDataCallBack:
        [conn onRTCP:(CFDataRef) data];
        break;

    default:
        NSLog(@"unexpected socket event");
        break;
    }
}

@implementation RTSPClientConnection

+ (RTSPClientConnection*) createWithSocket:(CFSocketNativeHandle) s server:(RTSPServer*) server
{
RTSPClientConnection* conn = [RTSPClientConnection alloc];
if ([conn initWithSocket:s Server:server] != nil)
{
    return conn;
}
return nil;
}

- (RTSPClientConnection*) initWithSocket:(CFSocketNativeHandle)s Server:(RTSPServer *)server
{
_state = ServerIdle;
_server = server;
CFSocketContext info;
memset(&info, 0, sizeof(info));
info.info = (void*)CFBridgingRetain(self);

_s = CFSocketCreateWithNative(nil, s, kCFSocketDataCallBack, onSocket, &info);

_rls = CFSocketCreateRunLoopSource(nil, _s, 0);
CFRunLoopAddSource(CFRunLoopGetMain(), _rls, kCFRunLoopCommonModes);

return self;
}

- (void) onSocketData:(CFDataRef)data
{
    //Code
}

- (NSString*) makeSDP
{
    //Code
}

- (void) onVideoData:(NSArray*) data time:(double) pts
{
    //Code
}

- (void) writeHeader:(uint8_t*) packet marker:(BOOL) bMarker time:(double) pts
{
    //Code
}

- (void) sendPacket:(uint8_t*) packet length:(int) cBytes
{
    //Code
}

- (void) onRTCP:(CFDataRef) data
{
// NSLog(@"RTCP recv");
}

- (void) tearDown
{
    // Code
}

- (void) shutdown
{
[self tearDown];
@synchronized(self)
{
    CFSocketInvalidate(_s);
    _s = nil;
}
}
@end

Благодаря.


person MK Singh    schedule 26.07.2013    source източник


Отговори (1)


Работих по него през последните 4 месеца, няма лесен начин да го направя. Трябва да кодирате свой собствен RTCP протокол.

редактиране: чух за RTPDump, но никога не съм опитвал

person HaneTV    schedule 30.07.2013
comment
Имали ли сте някога някакъв успех с това. На път съм да опитам същото и бих могъл да използвам някои насоки. - person hatebyte; 28.02.2014
comment
Направих функционална библиотека за поточно предаване на живо, свързана с Wowza Streaming Engine, така че да, възможно е. - person HaneTV; 28.02.2014
comment
Да, това се опитвам да направя. Опитвам се да създам връзка с отдалечен сокет към приложението wowza. Това ли е най-добрият маршрут или измислихте нещо, което работи по-добре? Все още нямам късмет. - person hatebyte; 28.02.2014