http://bbs.rosoo.net/blog-24408-8658.html
大家好:这是我写的流媒体客户端的实现,rtsp 是用tcp 实现的,rtp接收数据流 是用udp 实现的,rstp 部分沟通是ok 的,rtp 接收数据流也可以接收,但是每次接收数据流只能接收到2_4个包。我仔细研究过这几个包,刚好是一个完整一张图片。
请各位大侠帮忙看看,多多指导。
- (void)viewDidLoad
{
[super viewDidLoad];
Info = [[NSString alloc] init];
getport = 0;
socket = [[AsyncSocket alloc] initWithDelegate:self];
NSError *error = nil;
if(!([socket connectToHost:SERVERADDR onPort:SERVERPORT error:&error]))
{
NSLog(@"error:%@",error);
}
else
{
isRtp = 0;
}
socketudp = [[AsyncUdpSocket alloc] initWithDelegate:self];
}
/*
*建立连接,返回服务器对OPTIONS请求的响应
*/
-(NSMutableString*)getOptions
{
NSMutableString* options = [[[NSMutableString alloc] init] autorelease];
[options appendFormat:@"OPTIONS rtsp://%@/v1 RTSP/1.0%@",SERVERADDR,KENTER];
[options appendFormat:@"CSeq: 2%@",KENTER];
[options appendFormat:@"User-Agent: LibVLC/2.0.3 (LIVE555 Streaming Media v2011.12.23)%@%@",KENTER,KENTER];
NSLog(@"options = %@",options);
[socket writeData:[options dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];
NSMutableString* readString = [[[NSMutableString alloc] init] autorelease];
[socket readDataWithTimeout:3 tag:1];
return readString;
}
/*
*建立连接,返回服务器对DESCRIBE请求的响应
*/
-(NSMutableString*)getDescribe
{
NSMutableString* describe = [[[NSMutableString alloc] init] autorelease];
[describe appendFormat:@"DESCRIBE rtsp://%@/v1 RTSP/1.0%@",SERVERADDR,KENTER];
[describe appendFormat:@"CSeq: 3%@",KENTER];
[describe appendFormat:@"User-Agent: LibVLC/2.0.3 (LIVE555 Streaming Media v2011.12.23)%@",KENTER];
[describe appendFormat:@"Accept: application/sdp%@%@",KENTER,KENTER];
// [describe appendFormat:@"Authorization: Basic YWRtaW4=%@",KENTER];
NSLog(@"describe = %@",describe);
[socket writeData:[describe dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];
NSMutableString* readString = [[[NSMutableString alloc] init] autorelease];
[socket readDataWithTimeout:3 tag:2];
return readString;
}
/*
*建立连接,返回通过udp连接服务器对SETUP请求的响应
*/
-(NSMutableString*)getUdpSetup
{
NSMutableString* udpsetup = [[[NSMutableString alloc] init] autorelease];
[udpsetup appendFormat:@"SETUP rtsp://%@/v1/track0 RTSP/1.0%@",SERVERADDR,KENTER];
[udpsetup appendFormat:@"CSeq: 4%@",KENTER];
[udpsetup appendFormat:@"User-Agent: LibVLC/2.0.3 (LIVE555 Streaming Media v2011.12.23)%@",KENTER];
[udpsetup appendFormat:@"Transport: RTP/AVP;unicast;client_port=49664-49665%@%@",KENTER,KENTER];
NSLog(@"udpsetup = %@",udpsetup);
[socket writeData:[udpsetup dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];
NSMutableString* readString = [[[NSMutableString alloc] init] autorelease];
[socket readDataWithTimeout:3 tag:3];
return readString;
}
/*
*建立连接,返回向服务器对PLAY请求的响应
*/
-(NSMutableString*)getPlay:(NSString*)session
{
NSMutableString* play = [[[NSMutableString alloc] init] autorelease];
[play appendFormat:@"PLAY rtsp://%@/v1 RTSP/1.0%@",SERVERADDR,KENTER];
[play appendFormat:@"CSeq: 6%@",KENTER];
[play appendFormat:@"User-Agent: LibVLC/2.0.3 (LIVE555 Streaming Media v2011.12.23)%@",KENTER];
[play appendFormat:@"Session:%@%@",session,KENTER];
[play appendFormat:@"Range: npt=0.000-%@%@",KENTER,KENTER];
// [Info release];
NSLog(@"play = %@",play);
[socket writeData:[play dataUsingEncoding:NSUTF8StringEncoding] withTimeout:3 tag:1];
NSMutableString* readString = [[[NSMutableString alloc] init] autorelease];
[socket readDataWithTimeout:3 tag:4];
return readString;
}
-(void)RecvUDPData
{
// severs_port = [self getPort:Info];
// NSLog(@"severs_port = %d",severs_port);
NSError * error1 = nil;
[socketudp bindToPort:49664 error:nil];
if(error1)
{
NSLog(@"error1:%@",error1);
}
NSLog(@"start udp server");
// if ([socketudp connectToHost:SERVERADDR onPort:severs_port error:nil])
{
[socketudp receiveWithTimeout:-1 tag:0];//将不断接受摄像头发送的数据
}
}
/*
*通过主机名和端口号连接服务器
*/
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
NSLog(@"onSocket:%p didConnectToHost:%@ port:%hu", sock, host, port);
if(isRtp == 0)
{
[self getOptions];
}
else
{
NSLog(@"start tcp server");
[rtpTcp readDataWithTimeout:-1 tag:5];
}
}
/*
*向内存中写入数据
*/
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
NSString *message;
switch (tag)
{
case 1:
{
NSLog(@"getOptions:did read data");
message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if([[message substringToIndex:15] isEqualToString:@"RTSP/1.0 200 OK"])
{
// NSLog(@"message is: \n%@",message);
[message release];
[self getDescribe];
}
else
{
// NSLog(@"message is: \n%@",message);
[message release];
return;
}
}
break;
case 2:
{
NSLog(@"getDescribe:did read data");
message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if([[message substringToIndex:15] isEqualToString:@"RTSP/1.0 200 OK"])
{
// NSLog(@"message is: \n%@",message);
[message release];
[self getUdpSetup];
}
else
{
// NSLog(@"message is: \n%@",message);
[message release];
return;
}
}
break;
case 3:
{
NSLog(@"getUdpSetup:did read data");
message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if([[message substringToIndex:15] isEqualToString:@"RTSP/1.0 200 OK"])
{
// NSLog(@"message is: \n%@",message);
Info = message;
// NSLog(@"Info = %@",Info);
NSString* session = [self getSession:Info];
[self getPlay:session];
}
else
{
// NSLog(@"message is: \n%@",message);
[message release];
return;
}
}
break;
case 4:
{
NSLog(@"getPlay:did read data");
message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if([[message substringToIndex:15] isEqualToString:@"RTSP/1.0 200 OK"])
{
NSLog(@"message is: \n%@",message);
[message release];
[self RecvUDPData];
}
else
{
// NSLog(@"message is: \n%@",message);
[message release];
return;
}
}
break;
/*
case 5:
{
NSLog(@"getTeardown:did read data");
message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"message is: \n%@",message);
}
break;
*/
default:
break;
}
}
- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port
{
NSLog(@"start rece rtp by udp");
NSLog(@"length = %d ",[data length]);
Byte *testByte = (Byte *)[data bytes];
for(char i=12;i<[data length];i++)
{
printf("%02x",testByte[i]);
}
[socketudp receiveWithTimeout:-1 tag:0];
return YES;
}
- (void)onUdpSocket:(AsyncUdpSocket *)sock didNotReceiveDataWithTag:(long)tag dueToError:(NSError *)error
{
NSLog(@"UDP is missing");
[socketudp release];
socketudp = [[AsyncUdpSocket alloc] initWithDelegate:self];
[socketudp bindToPort:49664 error:nil];
[socketudp enableBroadcast:YES error:nil];//设置为广播
[socketudp receiveWithTimeout:-1 tag:0];//将不断接受摄像头发送的数据
}
@end
下面附上我的调试信息:
2012-08-22 19:28:04.619 TcpWebcanShow[6909:f803]
onSocket:0x6c23e30 didConnectToHost:192.168.8.37 port:554
2012-08-22 19:28:04.620 TcpWebcanShow[6909:f803] options =
OPTIONS rtsp://192.168.8.37/v1 RTSP/1.0
CSeq: 2
User-Agent: LibVLC/2.0.3 (LIVE555 Streaming Media v2011.12.23)
2012-08-22 19:28:04.628 TcpWebcanShow[6909:f803] getOptions:did read data
2012-08-22 19:28:04.629 TcpWebcanShow[6909:f803] message is:
RTSP/1.0 200 OK
CSeq: 2
Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, CMD
2012-08-22 19:28:04.629 TcpWebcanShow[6909:f803] describe =
DESCRIBE rtsp://192.168.8.37/v1 RTSP/1.0
CSeq: 3
User-Agent: LibVLC/2.0.3 (LIVE555 Streaming Media v2011.12.23)
Accept: application/sdp
2012-08-22 19:28:04.632 TcpWebcanShow[6909:f803] getDescribe:did read data
2012-08-22 19:28:04.633 TcpWebcanShow[6909:f803] message is:
RTSP/1.0 200 OK
CSeq: 3
Date: Date: Tue, Aug 21 2012 19:22:20 GMT+0800
Content-Base: rtsp://192.168.8.37/v1/
Content-Type: application/sdp
Content-Length: 465
v=0
o=- 1 1 IN IP4 127.0.0.1
s=v1
i=Live
t=0 0
a=tool:Sunamper Live Media Streamer
a=type:broadcast
a=control:*
a=range:npt=0-
a=x-qt-text-nam:v1
a=x-qt-text-inf:Live
c=IN IP4 0.0.0.0
a=x-xframerate:20
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=000001;sprop-parameter-sets=Z0IAKOkBaHsg,aM4xUg==
a=control:track0
m=audio 0 RTP/AVP 97
a=rtpmap:97 AMR/8000
a=fmtp:97 octet-align=1
a=control:track1
2012-08-22 19:28:04.633 TcpWebcanShow[6909:f803] udpsetup =
SETUP rtsp://192.168.8.37/v1/track0 RTSP/1.0
CSeq: 4
User-Agent: LibVLC/2.0.3 (LIVE555 Streaming Media v2011.12.23)
Transport: RTP/AVP;unicast;client_port=49664-49665
2012-08-22 19:28:04.639 TcpWebcanShow[6909:f803] getUdpSetup:did read data
2012-08-22 19:28:04.640 TcpWebcanShow[6909:f803] message is:
RTSP/1.0 200 OK
CSeq: 4
Date: Date: Tue, Aug 21 2012 19:22:20 GMT+0800
Transport: RTP/AVP;unicast;distination=192.168.8.204;source=192.168.8.37;client_port=49664-49665;server_port=57208-57209
Session: 4CD08825B705749A93351455111778
2012-08-22 19:28:04.641 TcpWebcanShow[6909:f803] play =
PLAY rtsp://192.168.8.37/v1 RTSP/1.0
CSeq: 6
User-Agent: LibVLC/2.0.3 (LIVE555 Streaming Media v2011.12.23)
Session:4CD08825B705749A93351455111778
Range: npt=0.000-
2012-08-22 19:28:04.644 TcpWebcanShow[6909:f803] getPlay:did read data
2012-08-22 19:28:04.644 TcpWebcanShow[6909:f803] message is:
RTSP/1.0 200 OK
CSeq: 6
Date: Date: Tue, Aug 21 2012 19:22:20 GMT+0800
Session: 4CD08825B705749A93351455111778
Range: npt=0.000-
RTP-Info: url=rtsp://192.168.8.37/v1/track0;seq=53324;rtptime=629723212
2012-08-22 19:28:04.645 TcpWebcanShow[6909:f803] start udp server
2012-08-22 19:28:04.666 TcpWebcanShow[6909:f803] start rece rtp by udp
2012-08-22 19:28:04.667 TcpWebcanShow[6909:f803] length = 1028
419a660a6301bf824e047bc7f9eff572f8032b6bbbdbe239700afec0dd37cdcbc3bfbf2f848d8ef049e1338bd3a8679b802bbfe5efbe978279019848e5eb9d1430780f57c47e4108f34660c0f1df93848c319ae7aa6d7fe4f006de5b3e762ebd7c54059acd92fbac3f07e0cbfc9d873c2734aef2