983 lines
28 KiB
Plaintext
Executable File
983 lines
28 KiB
Plaintext
Executable File
1. Test
|
|
Result Case
|
|
---------------------------------------------------------------------------
|
|
OK Init the server.
|
|
OK Start the server.
|
|
OK Stop the server.
|
|
OK Reset the server.
|
|
OK Force reset the server.
|
|
OK Allocate queues.
|
|
OK Release queues.
|
|
OK Register streams.
|
|
OK Deregister a stream with/without ongoing streaming.
|
|
OK Set the file path.
|
|
OK VLC.
|
|
OK QuickTime player.
|
|
OK rtsp_test.
|
|
OK Live 1-1
|
|
OK Live 1-M
|
|
OK Live multiple 1-1
|
|
OK Live multiple 1-M
|
|
OK Live teardown
|
|
OK File 1-1
|
|
OK File 1-M
|
|
OK File multiple 1-1
|
|
OK File multiple 1-M
|
|
File pause (not supported by spook)
|
|
OK File teardown
|
|
OK Abnormal connection termination by clients.
|
|
OK Deregister corresponding file stream even if abnormal connection
|
|
termination by clients.
|
|
OK 135 clients for 47832 seconds.
|
|
OK Client listing test.
|
|
OK Client listing test with 1 consistent and 19 dynamic clients for
|
|
XXXXX seconds.
|
|
|
|
2. Done by the streaming server:
|
|
(1) Close the usock & unlink the file.
|
|
(2) STREAM_THREAD_START, STREAM_THREAD_STOP, STREAM_THREAD_RESET.
|
|
(3) media enqueue, media flush.
|
|
(4) stream deregistration.
|
|
(5) SIGKILL.
|
|
|
|
3. utility functions
|
|
global:
|
|
config_port
|
|
config_rtprange
|
|
config_frameheap
|
|
rtsp:
|
|
set_track
|
|
set_path
|
|
set_qos
|
|
http:
|
|
set_input
|
|
set_path
|
|
set_mode
|
|
set_max_cache_time
|
|
|
|
4. FStreamer.conf (OV7725, 3CH, H264_MP2_640x480_30FPS, MP4_AMR_640x480_30FPS, MJPEG_MP2_640x480_30FPS)
|
|
FrameHeap 300 300;
|
|
FrameHeap 20 4096;
|
|
FrameHeap 20 40000;
|
|
FrameHeap 10 80000;
|
|
FrameHeap 2 400000;
|
|
|
|
Port 554;
|
|
|
|
Authentication 0 10;
|
|
|
|
RtpRange 50000 60000;
|
|
|
|
external.c ---
|
|
Input External { start_block::ext=(struct ext_input *)malloc()
|
|
Format "h264";
|
|
CallNumber 201;
|
|
Framerate 1 30;
|
|
Output h264v1; set_output::struct stream *new_stream(...,ext)
|
|
}
|
|
|
|
Input External {
|
|
Format "mpeg4";
|
|
CallNumber 202;
|
|
Framerate 1 30;
|
|
Output mpeg4v2;
|
|
}
|
|
|
|
Input External {
|
|
Format "jpeg";
|
|
CallNumber 203;
|
|
Framerate 1 30;
|
|
Output mjpegv3;
|
|
}
|
|
|
|
Input DSP2 {
|
|
AudioOutput pcm2;
|
|
AudioRate 16000;
|
|
AudioChannels 1;
|
|
}
|
|
|
|
Filter Resample2 {
|
|
Input "pcm2";
|
|
Output "pcm2-8k";
|
|
Rate 8000;
|
|
Channels 1;
|
|
}
|
|
|
|
Encoder AMRv2 {
|
|
Input "pcm2-8k";
|
|
Mode MR515;
|
|
Output "amrv2";
|
|
}
|
|
|
|
Encoder MP2v2 {
|
|
Input "pcm2";
|
|
Bitrate 32000;
|
|
Output "mp2v2";
|
|
}
|
|
|
|
Record-ch1 Record {
|
|
Format "AVI";
|
|
Path /mnt/sd/recording ;
|
|
Track "h264v1";
|
|
Track "mp2v2";
|
|
}
|
|
|
|
Record-ch2 Record {
|
|
Format "AVI";
|
|
Path /mnt/sd/recording ;
|
|
Track "mpeg4v2";
|
|
Track "mp2v2";
|
|
}
|
|
|
|
Record-ch3 Record {
|
|
Format "AVI";
|
|
Path /mnt/sd/recording ;
|
|
Track "mjpegv3";
|
|
Track "mp2v2";
|
|
}
|
|
|
|
live.c ---
|
|
RTSP-Handler Live { start_block::(struct live_source *)malloc()
|
|
Path / ; set_path::new_rtsp_location(...,live_open,..)::(struct rtsp_location *)malloc()
|
|
Track "h264v1"; set_track::struct stream_destination *connect_to_stream()
|
|
struct rtp_media *new_rtp_media_XXX()
|
|
Track "mp2v2";
|
|
}
|
|
|
|
live_open() ---
|
|
ls = (struct live_session *)malloc()
|
|
ls->sess = new_session();
|
|
|
|
RTSP-Handler Live {
|
|
Path /3g ;
|
|
Track "h264v1";
|
|
Track "amrv2";
|
|
}
|
|
|
|
RTSP-Handler Live {
|
|
Path /v2 ;
|
|
Track "mpeg4v2";
|
|
Track "mp2v2";
|
|
}
|
|
|
|
RTSP-Handler Live {
|
|
Path /3gv2 ;
|
|
Track "mpeg4v2";
|
|
Track "amrv2";
|
|
}
|
|
|
|
RTSP-Handler Live {
|
|
Path /v3 ;
|
|
Track "mjpegv3";
|
|
Track "mp2v2";
|
|
}
|
|
|
|
RTSP-Handler Live {
|
|
Path /3gv3 ;
|
|
Track "mjpegv3";
|
|
Track "amrv2";
|
|
}
|
|
|
|
5.
|
|
live_init
|
|
start_block, 0x7fd800
|
|
start_block, thread 114696
|
|
set_path, /, 0x7fd800
|
|
set_track, h264v1, 0x7fd800
|
|
set_track, mp2v2, 0x7fd800
|
|
end_block, 0x7fd800
|
|
start_block, 0x801198
|
|
set_path, /3g, 0x801198
|
|
set_track, h264v1, 0x801198
|
|
set_track, amrv2, 0x801198
|
|
end_block, 0x801198
|
|
next_live_frame
|
|
live_loop
|
|
next_live_frame
|
|
next_live_frame
|
|
next_live_frame
|
|
|
|
6.
|
|
Defined in conf_parse.h:
|
|
RTCP_ENABLE
|
|
GM
|
|
|
|
STRUCTURE
|
|
struct rtsp_location {
|
|
struct loc_node node;
|
|
char realm[128];
|
|
char username[128];
|
|
char password[128];
|
|
open_func open;
|
|
void *private;
|
|
};
|
|
|
|
struct live_source {
|
|
struct live_session *sess_list;
|
|
struct live_track track[MAX_TRACKS];
|
|
int qos;
|
|
int safe_I_num;
|
|
int curr_I_num;
|
|
int I_frame_only;
|
|
pthread_t live_thread;
|
|
};
|
|
|
|
struct live_track {
|
|
int index;
|
|
struct live_source *source;
|
|
struct stream_destination *stream;
|
|
int ready;
|
|
struct rtp_media *rtp;
|
|
};
|
|
|
|
struct live_session {
|
|
struct live_session *next;
|
|
struct live_session *prev;
|
|
struct session *sess;
|
|
struct live_source *source;
|
|
int playing;
|
|
int delay;
|
|
};
|
|
|
|
struct rtsp_session {
|
|
struct rtsp_session *next;
|
|
struct rtsp_session *prev;
|
|
char id[32];
|
|
struct session *sess;
|
|
};
|
|
|
|
struct session {
|
|
struct session *next;
|
|
struct session *prev;
|
|
get_sdp_func get_sdp;
|
|
setup_func setup;
|
|
play_func play;
|
|
pause_func pause;
|
|
teardown_func teardown;
|
|
void *private;
|
|
session_close_func control_close;
|
|
void *control_private;
|
|
struct timeval open_time;
|
|
char addr[64];
|
|
struct rtp_endpoint *ep[MAX_TRACKS];
|
|
int stream_num;
|
|
};
|
|
|
|
struct stream {
|
|
struct stream *next;
|
|
struct stream *prev;
|
|
char name[256];
|
|
int format;
|
|
struct stream_destination *dest_list;
|
|
void (*get_framerate)( struct stream *s, int *fincr, int *fbase );
|
|
void (*get_bitrate)( struct stream *s, int *bitrate );
|
|
void (*get_framesize)( struct stream *s, int *framesize );
|
|
void (*set_running)( struct stream *s, int running );
|
|
void *src_private;
|
|
};
|
|
|
|
struct stream_destination {
|
|
struct stream_destination *next;
|
|
struct stream_destination *prev;
|
|
struct stream *stream;
|
|
int waiting;
|
|
frame_deliver_func process_frame;
|
|
void *d;
|
|
};
|
|
|
|
struct rtp_endpoint {
|
|
struct session *session;
|
|
int payload;
|
|
int max_data_size;
|
|
unsigned int ssrc;
|
|
unsigned int start_timestamp;
|
|
unsigned int last_timestamp;
|
|
unsigned int sync_timestamp;
|
|
unsigned int pre_sync_timestamp;
|
|
unsigned int timebase;
|
|
short packetskip;
|
|
unsigned int delay_time;
|
|
short stopdetect;
|
|
int seqnum;
|
|
int packet_count;
|
|
int octet_count;
|
|
struct event *rtcp_send_event;
|
|
int enable_send_rtcp; //kevin 2007.1.17
|
|
int force_rtcp;
|
|
int event_enabled;//kevin rtcp enabling flag
|
|
struct timeval last_rtcp_recv;
|
|
int retry;
|
|
int trans_type;
|
|
union {
|
|
struct {
|
|
char sdp_addr[48];
|
|
int sdp_port;
|
|
int rtp_fd;
|
|
struct event *rtp_event;
|
|
int rtcp_fd;
|
|
struct event *rtcp_event;
|
|
struct conn *conn;
|
|
int rtp_chan;
|
|
} udp;
|
|
struct {
|
|
struct conn *conn;
|
|
int rtp_chan;
|
|
int rtcp_chan;
|
|
} inter;
|
|
} trans;
|
|
|
|
int enable_send_rtcp_app_motionNty;
|
|
int timeSec_rtcp_app_motionNty;
|
|
int flyKey;
|
|
};
|
|
|
|
struct conn {
|
|
struct conn *next;
|
|
struct conn *prev;
|
|
int fd;
|
|
int second_fd; /* QuickTime uses two TCP connections for tunneling */
|
|
struct sockaddr_in client_addr;
|
|
struct event *read_event;
|
|
struct event *second_read_event; /* for second_fd */
|
|
struct event *write_event;
|
|
int proto;
|
|
char http_tunnel_cookie[128]; /* used to identify QuickTime tunnels */
|
|
int base64_count; /* QuickTime uses base64 when tunneling over HTTP */
|
|
unsigned char req_buf[4096];
|
|
int req_len;
|
|
struct req *req_list;
|
|
#ifdef NO_MM
|
|
unsigned char send_buf[16384];
|
|
// unsigned char send_buf[PACKET_SIZE+500];
|
|
#else
|
|
unsigned char send_buf[65536];
|
|
#endif
|
|
int send_buf_r;
|
|
int send_buf_w;
|
|
int drop_after;
|
|
void *proto_state;
|
|
};
|
|
|
|
GLOBAL
|
|
struct loc_node *rtsp_loc_list
|
|
struct stream *stream_list
|
|
struct session *sess_list
|
|
|
|
LOCAL
|
|
struct rtsp_session *sess_list; // rtsp.c
|
|
|
|
|
|
// spook_log_init(): Init spook log.
|
|
|
|
// acl_init(): Init access control list.
|
|
|
|
// control_init(): Init an unix socket as the control channel.
|
|
|
|
external_init(): Init external input module.
|
|
input external
|
|
start_block(): Allocate struct ext_input
|
|
set_output():
|
|
ext_input.output = (struct stream *) new_stream();
|
|
Allocate struct stream.
|
|
+ Add allocated struct stream to stream_list.
|
|
stream.src_private = &ext_input;
|
|
ext_input.output->get_framerate = get_framerate;
|
|
ext_input.output->set_running = [static] set_running;
|
|
set_format(): Set format (h264/mp4/mjpeg/mpa/amr...).
|
|
set_framerate()
|
|
set_callnumber(): Set call number (data channel number).
|
|
|
|
// access_log_init(): Init access log.
|
|
|
|
dsp1_init(): Init 1st audio channel.
|
|
input DSP1
|
|
start_block():
|
|
Allocate a struct v4l_input.
|
|
v4l_input.format = FORMAT_PCM;
|
|
set_aout()
|
|
v4l_input.aout = (struct stream *) new_stream(..., FORMAT_PCM, &v4l_input);
|
|
Allocate struct stream.
|
|
+ Add allocated struct stream to stream_list.
|
|
stream.src_private = &v4l_input;
|
|
set_audiorate()
|
|
set_audiochannels()
|
|
end_block():
|
|
audio = open(AUDIO1, O_RDONLY, 0);
|
|
v4l_input.aq = new_soft_queue( 10 );
|
|
add_softqueue_event(v4l_input.aq, 0, get_back_audio_frame, &v4l_input);
|
|
pthread_create(&v4l_input.audio_thread, NULL, audio_loop, &v4l_input);
|
|
|
|
dsp2_init(): Init 2nd audio channel
|
|
input DSP2
|
|
set_aout()
|
|
set_audiorate()
|
|
set_audiochannels()
|
|
|
|
// scull_init(all audio channels):
|
|
input SCULL1,SCULL2
|
|
start_block():
|
|
Allocate a struct v4l_input.
|
|
v4l_input.format = FORMAT_PCM;
|
|
set_aout()
|
|
v4l_input.aout = (struct stream *) new_stream(..., FORMAT_PCM, &v4l_input);
|
|
Allocate struct stream.
|
|
+ Add allocated struct stream to stream_list.
|
|
stream.src_private = &v4l_input;
|
|
set_audiorate()
|
|
set_audiochannels()
|
|
end_block():
|
|
audio = open(SCULL1, O_RDWR, 0);
|
|
v4l_input.aq = new_soft_queue( 10 );
|
|
add_softqueue_event(v4l_input.aq, 0, get_back_audio_frame, &v4l_input);
|
|
pthread_create(&v4l_input.audio_thread, NULL, audio_loop, &v4l_input);
|
|
|
|
// mp2_v2_init() as
|
|
mp2_init_ext(all audio channels):
|
|
encoder mp2v1,mp2v2
|
|
start_block():
|
|
Allocate a struct mp2_encoder.
|
|
set_input():
|
|
mp2_encoder.input = (stream_destination *) connect_to_stream(..., mp2_encode, &mp2_encoder, ...);
|
|
Find stream.
|
|
new_dest(&stream, mp2_encode, &mp2_encoder)
|
|
Allocate a struct stream_destination.
|
|
+ Add stream_destination to stream.dest_list.
|
|
stream_destination.stream = &stream;
|
|
stream_destination.process_frame = mp2_encode;
|
|
stream_destination.d = &mp2_encoder;
|
|
set_output():
|
|
mp2_encoder.output = new_stream(..., FORMAT_MPA, &mp2_encoder);
|
|
Allocate struct stream.
|
|
+ Add allocated struct stream to stream_list.
|
|
stream.src_private = &mp2_encoder;
|
|
mp2_encoder.output->get_framerate = [static] get_framerate;
|
|
mp2_encoder.output->get_bitrate = [static] get_bitrate;
|
|
mp2_encoder.output->set_running = [static] set_running;
|
|
set_bitrate():
|
|
end_block():
|
|
MPA_encode_init(&mp2_encoder.ctx, ...);
|
|
mp2_encoder.inq = new_soft_queue(16);
|
|
mp2_encoder.outq = new_soft_queue(16);
|
|
add_softqueue_event(mp2_encoder.outq, 0, [static] get_back_frame, &mp2_encoder);
|
|
pthread_create(&mp2_encoder.thread, NULL, mp2_loop, &mp2_encoder);
|
|
|
|
amr_init_ext(all audio channels):
|
|
encoder amrv1,amrv2
|
|
start_block():
|
|
Allocate a struct amr_encoder.
|
|
set_input():
|
|
amr_encoder.input = (stream_destination *) connect_to_stream(..., amr_encode, &amr_encoder, ...);
|
|
Find stream.
|
|
new_dest(&stream, amr_encode, &amr_encoder)
|
|
Allocate a struct stream_destination.
|
|
+ Add stream_destination to stream.dest_list.
|
|
stream_destination.stream = &stream;
|
|
stream_destination.process_frame = amr_encode;
|
|
stream_destination.d = &amr_encoder;
|
|
set_output():
|
|
mp2_encoder.output = new_stream(..., FORMAT_AMR, &amr_encoder);
|
|
Allocate struct stream.
|
|
+ Add allocated struct stream to stream_list.
|
|
stream.src_private = &amr_encoder;
|
|
amr_encoder.output->set_running = [static] set_running;
|
|
set_mode(): AMR475,MR515,MR59,MR67,MR74,MR795,MR102,MR122
|
|
end_block():
|
|
Speech_Encode_Frame_init(&amr_encoder.speech_encoder_state, ...)
|
|
sid_sync_init(&sid_state)
|
|
amr_encoder.inq = new_soft_queue(16);
|
|
amr_encoder.outq = new_soft_queue(16);
|
|
add_softqueue_event(amr_encoder.outq, 0, [static] get_back_frame, &amr_encoder);
|
|
pthread_create(&amr_encoder.thread, NULL, amr_loop, &amr_encoder);
|
|
|
|
live_init()
|
|
rtsp-handler live
|
|
start_block():
|
|
Allocate a struct live_source.
|
|
live_source.track[i].index = i;
|
|
live_source.track[i].source = &live_source;
|
|
if([static] live_loop_thread_created == 0)
|
|
pthread_create(&live_source.live_thread), NULL, live_loop, &live_source);
|
|
set_path(..., &live_source):
|
|
new_rtsp_location(..., live_open, &live_source);
|
|
Allocate a struct rtsp_location.
|
|
+ Add rtsp_location to rtsp_loc_list.
|
|
rtsp_location.open = live_open;
|
|
rtsp_location.private = &live_source;
|
|
set_track(..., &live_source):
|
|
live_source.track[t].stream = (stream_destination *) connect_to_stream(..., next_live_frame, &live_source.track[t],...)
|
|
Find stream.
|
|
new_dest(&stream, next_live_frame, &live_source.track[t])
|
|
Allocate a struct stream_destination.
|
|
+ Add stream_destination to stream.dest_list.
|
|
stream_destination.stream = &stream;
|
|
stream_destination.process_frame = next_live_frame;
|
|
stream_destination.d = &live_source.track[t];
|
|
case FORMAT_MPEG4:
|
|
live_source.track[t].rtp = new_rtp_media_mpeg4();
|
|
Allocate a struct rtp_mpeg4.
|
|
new_rtp_media(mpeg4_get_sdp, mpeg4_get_payload, mpeg4_process_frame, mpeg4_send, &rtp_mpeg4);
|
|
Allocate a struct rtp_media.
|
|
...
|
|
rtp_media.private = &rtp_mpeg4;
|
|
case FORMAT_H264:
|
|
live_source.track[t].rtp = new_rtp_media_h264(live_source.track[t].stream->stream);
|
|
Allocate a struct rtp_h264.
|
|
new_rtp_media(h264_get_sdp, h264_get_payload, h264_process_frame, h264_send, &rtp_h264);
|
|
Allocate a struct rtp_media.
|
|
...
|
|
rtp_media.private = &rtp_h264;
|
|
case FORMAT_JPEG:
|
|
live_source.track[t].rtp = new_rtp_media_jpeg_stream(live_source.track[t].stream->stream);
|
|
Allocate a struct rtp_jpeg.
|
|
new_rtp_media(jpeg_get_sdp, jpeg_get_payload, jpeg_process_frame, jpeg_send, &rtp_jpeg);
|
|
Allocate a struct rtp_media.
|
|
...
|
|
rtp_media.private = &rtp_jpeg;
|
|
case FORMAT_MPA:
|
|
live_source.track[t].rtp = new_rtp_media_mpa(live_source.track[t].stream->stream);
|
|
Allocate a struct rtp_mpa.
|
|
new_rtp_media(mpa_get_sdp, mpa_get_payload, mpa_process_frame, mpa_send, &rtp_mpa);
|
|
Allocate a struct rtp_media.
|
|
...
|
|
rtp_media.private = &rtp_mpa;
|
|
case FORMAT_AMR:
|
|
live_source.track[t].rtp = new_rtp_media_amr(live_source.track[t].stream->stream);
|
|
Allocate a struct rtp_amr.
|
|
new_rtp_media(amr_get_sdp, amr_get_payload, amr_process_frame, amr_send, &rtp_amr);
|
|
Allocate a struct rtp_media.
|
|
...
|
|
rtp_media.private = &rtp_amr;
|
|
set_qos(..., &live_source):
|
|
end_block(..., &live_source);
|
|
Check live_source.track[0].rtp != NULL.
|
|
|
|
http_init()
|
|
output http
|
|
start_block():
|
|
Allocate a struct http_location.
|
|
+ Add http_location to http_loc_list.
|
|
set_input():
|
|
http_location.input = connect_to_stream(..., jpeg_next_frame, &http_location, FORMAT_JPEG)
|
|
Find stream.
|
|
new_dest(&stream, jpeg_next_frame, &http_location)
|
|
Allocate a struct stream_destination.
|
|
+ Add stream_destination to stream.dest_list.
|
|
stream_destination.stream = &stream;
|
|
stream_destination.process_frame = jpeg_next_frame;
|
|
stream_destination.d = &http_location;
|
|
set_path():
|
|
set_mode():
|
|
http_location.streaming = 0 "single" or 1 "stream".
|
|
set_max_cache_time():
|
|
end_block():
|
|
Check http_location.input, http_location.node.path.
|
|
|
|
read_config_file()
|
|
event_loop(0)
|
|
|
|
handle_OPTIONS():
|
|
DESCRIBE, SETUP, TEARDOWN, PLAY
|
|
|
|
handle_DESCRIBE():
|
|
loc = (rtsp_location *) find_rtsp_location(req->req->sl.req.uri, path, NULL)
|
|
sess = (struct session *) rtsp_location.open(path, (live_source *)loc->private)
|
|
if (0 < sess->get_sdp()) {
|
|
if (0 <= tcp_send_pmsg(req->conn, req->resp, sdp_len))
|
|
send_data(req->conn, sdp, sdp_len);
|
|
}
|
|
sess->teardown(sess, NULL);
|
|
|
|
handle_SETUP():
|
|
loc = (rtsp_location *) find_rtsp_location( req->req->sl.req.uri, path, &track)
|
|
if SESSION
|
|
rs = (struct rtsp_session *) get_session(SESSION)
|
|
s = rs->sess
|
|
else
|
|
s = (structure session *) loc->open(path, (live_source *) loc->private) [live_open]
|
|
Allocate a struct live_session.
|
|
live_source.sess_list = &live_session;
|
|
live_session.sess = new_session();
|
|
Allocate a struct session.
|
|
+ Add session to sess_list.
|
|
live_session.source = &live_source;
|
|
...
|
|
live_session.sess->private = &live_session;
|
|
return live_session.sess;
|
|
s->setup(s, track) [live_setup]
|
|
s->ep[t] = new_rtp_endpoint(payload);
|
|
Allocate a struct rtp_endpoint.
|
|
if RTCP_ENABLE & Video
|
|
rtp_endpoint.rtcp_send_event = add_timer_event(30000, 0, rtcp_app_fire, &rtp_endpoint);
|
|
set_event_enabled(rtp_endpoint.rtcp_send_event, 0 );
|
|
s->ep[t]->session = s;
|
|
s->ep[t]->flyKey = getFlyKey(ls->source->track[t].stream->stream->name);
|
|
if RTP/AVP/TCP
|
|
ret = rtsp_interleave_setup(s, track, req, t);
|
|
Allocate a struct rtsp_conn.
|
|
req->conn->proto_state = &rtsp_conn;
|
|
rtsp_conn.ichan[rtp_chan].ep = s->ep[track];
|
|
rtsp_conn.ichan[rtp_chan].rtcp = 0;
|
|
if RTCP_ENABLE
|
|
rtsp_conn.ichan[rtcp_chan].ep = s->ep[track];
|
|
rtsp_conn.ichan[rtcp_chan].rtcp = 1;
|
|
endif
|
|
connect_interleaved_endpoint(s->ep[track], req->conn, rtp_chan, rtcp_chan);
|
|
else
|
|
ret = rtsp_udp_setup(s, track, req, t);
|
|
if (ret < 0)
|
|
s->teardown(s, s->ep[track]); [live_teardown]
|
|
else
|
|
tcp_send_pmsg(req->conn, req->resp, -1);
|
|
if(!rs) rs = new_rtsp_session(struct session *);
|
|
Allocate a struct rtsp_session.
|
|
Add rtsp_session to sess_list[local].
|
|
rtsp.session.sess = &session;
|
|
session->control_private = &rtsp_session;
|
|
session->control_close = rtsp_session_close();
|
|
|
|
handle_SET_PARAMETER():
|
|
|
|
handle_GET_PARAMETER():
|
|
|
|
handle_PLAY():
|
|
rs = (struct rtsp_session *) get_session(get_header(req->req, "Session"))
|
|
rs->sess->play(rs->sess, have_start ? &start : NULL); [live_play]
|
|
ls = (struct live_session *)s->private;
|
|
For each active tracks
|
|
set_waiting(ls->source->track[t].stream, 1);
|
|
tcp_send_pmsg(req->conn, req->resp, -1);
|
|
|
|
handle_PAUSE():
|
|
|
|
handle_TEARDOWN():
|
|
loc = (rtsp_location *) find_rtsp_location( req->req->sl.req.uri, NULL, &track)
|
|
rs = (struct rtsp_session *) get_session(get_header( req->req, "Session"))
|
|
tcp_send_pmsg(req->conn, req->resp, -1);
|
|
rs->sess->teardown( rs->sess, track < 0 ? NULL : rs->sess->ep[track]); [live_teardown]
|
|
ls = (struct live_session *)s->private;
|
|
For each ative track
|
|
del_rtp_endpoint(s->ep[i]);
|
|
if RTCP_ENABLE
|
|
remove_event(ep->rtcp_send_event);
|
|
case RTP_TRANS_UDP:
|
|
remove_event(ep->trans.udp.rtp_event);
|
|
close(ep->trans.udp.rtp_fd);
|
|
if RTCP_ENABLE
|
|
remove_event(ep->trans.udp.rtcp_event);
|
|
close(ep->trans.udp.rtcp_fd);
|
|
interleave_disconnect(ep->trans.udp.conn, ep->trans.udp.rtp_chan);
|
|
case RTP_TRANS_INTER:
|
|
interleave_disconnect(ep->trans.inter.conn, ep->trans.inter.rtp_chan);
|
|
ifd RTCP_ENABLE
|
|
interleave_disconnect(ep->trans.inter.conn, ep->trans.inter.rtcp_chan);
|
|
free( ep );
|
|
track_check_running(ls->source, i);
|
|
if (remaining == 0)
|
|
Free ls.
|
|
del_session((struct session *) sess);
|
|
Remove sess from sess_list.
|
|
sess->control_close(sess); [rtsp_session_close]
|
|
rs = (struct rtsp_session *) sess->control_private;
|
|
Remove sess from sess_list ???
|
|
Free rs.
|
|
Free sess.
|
|
|
|
7. RTSP session examples
|
|
(1) VLC
|
|
|
|
OPTIONS rtsp://192.168.68.236:554/live/ch09 RTSP/1.0
|
|
CSeq: 7
|
|
User-Agent: VLC media player (LIVE555 Streaming Media v2009.04.20)
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 7
|
|
Server: VStream Streaming Server V1.0
|
|
Public: DESCRIBE, SETUP, TEARDOWN, PLAY
|
|
|
|
DESCRIBE rtsp://192.168.68.236:554/live/ch09 RTSP/1.0
|
|
CSeq: 8
|
|
Accept: application/sdp
|
|
User-Agent: VLC media player (LIVE555 Streaming Media v2009.04.20)
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 8
|
|
Server: VStream Streaming Server V1.0
|
|
Content-Base: rtsp://192.168.68.236:554/live/ch09/
|
|
Content-Type: application/sdp
|
|
Content-Length: 355
|
|
|
|
SETUP rtsp://192.168.68.236:554/live/ch09/trackID=0 RTSP/1.0
|
|
CSeq: 9
|
|
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
|
|
User-Agent: VLC media player (LIVE555 Streaming Media v2009.04.20)
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 9
|
|
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
|
|
Session: A6843ED31907451D9E91
|
|
|
|
SETUP rtsp://192.168.68.236:554/live/ch09/trackID=1 RTSP/1.0
|
|
CSeq: 10
|
|
Transport: RTP/AVP/TCP;unicast;interleaved=2-3
|
|
Session: A6843ED31907451D9E91
|
|
User-Agent: VLC media player (LIVE555 Streaming Media v2009.04.20)
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 10
|
|
Transport: RTP/AVP/TCP;unicast;interleaved=2-3
|
|
Session: A6843ED31907451D9E91
|
|
|
|
PLAY rtsp://192.168.68.236:554/live/ch09/ RTSP/1.0
|
|
CSeq: 11
|
|
Session: A6843ED31907451D9E91
|
|
Range: npt=0.000-
|
|
User-Agent: VLC media player (LIVE555 Streaming Media v2009.04.20)
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 11
|
|
Session: A6843ED31907451D9E91
|
|
Range: npt=now-
|
|
RTP-Info: url=rtsp://192.168.68.236:554/live/ch09//trackID=0;seq=14535;rtptime=0,url=rtsp://192.168.68.236:554/live/ch09//trackID=1;seq=6167;rtptime=0
|
|
|
|
TEARDOWN rtsp://192.168.68.236:554/live/ch09/ RTSP/1.0
|
|
CSeq: 12
|
|
Session: A6843ED31907451D9E91
|
|
User-Agent: VLC media player (LIVE555 Streaming Media v2009.04.20)
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 12
|
|
Session: A6843ED31907451D9E91
|
|
|
|
(2) QuickTime
|
|
|
|
DESCRIBE rtsp://192.168.68.236:554/file/2009-12-14.avi RTSP/1.0
|
|
CSeq: 1
|
|
Accept: application/sdp
|
|
Bandwidth: 2147483647
|
|
Accept-Language: en-GB
|
|
User-Agent: QuickTime/7.5.5 (qtver=7.5.5;os=Windows NT 5.1Service Pack 3)
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 1
|
|
Server: VStream Streaming Server V1.0
|
|
Content-Base: rtsp://192.168.68.236:554/file/2009-12-14.avi/
|
|
Content-Type: application/sdp
|
|
Content-Length: 351
|
|
|
|
SETUP rtsp://192.168.68.236:554/file/2009-12-14.avi/trackID=0 RTSP/1.0
|
|
CSeq: 2
|
|
Transport: RTP/AVP/TCP;unicast
|
|
x-dynamic-rate: 1
|
|
x-transport-options: late-tolerance=2.900000
|
|
User-Agent: QuickTime/7.5.5 (qtver=7.5.5;os=Windows NT 5.1Service Pack 3)
|
|
Accept-Language: en-GB
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 2
|
|
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
|
|
Session: C85B60A2961D9DE3AC08
|
|
|
|
SETUP rtsp://192.168.68.236:554/file/2009-12-14.avi/trackID=1 RTSP/1.0
|
|
CSeq: 3
|
|
Transport: RTP/AVP/TCP;unicast
|
|
x-dynamic-rate: 1
|
|
x-transport-options: late-tolerance=2.900000
|
|
Session: C85B60A2961D9DE3AC08
|
|
User-Agent: QuickTime/7.5.5 (qtver=7.5.5;os=Windows NT 5.1Service Pack 3)
|
|
Accept-Language: en-GB
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 3
|
|
Transport: RTP/AVP/TCP;unicast;interleaved=2-3
|
|
Session: C85B60A2961D9DE3AC08
|
|
|
|
PLAY rtsp://192.168.68.236:554/file/2009-12-14.avi RTSP/1.0
|
|
CSeq: 4
|
|
Range: npt=0.000000-
|
|
x-prebuffer: maxtime=2.000000
|
|
Session: C85B60A2961D9DE3AC08
|
|
User-Agent: QuickTime/7.5.5 (qtver=7.5.5;os=Windows NT 5.1Service Pack 3)
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 4
|
|
Session: C85B60A2961D9DE3AC08
|
|
Range: npt=now-
|
|
RTP-Info: url=rtsp://192.168.68.236:554/file/2009-12-14.avi/trackID=0;seq=9332;rtptime=0,url=rtsp://192.168.68.236:554/file/2009-12-14.avi/trackID=1;seq=1469;rtptime=0
|
|
|
|
PAUSE rtsp://192.168.68.236:554/file/2009-12-14.avi RTSP/1.0
|
|
CSeq: 5
|
|
Session: C85B60A2961D9DE3AC08
|
|
User-Agent: QuickTime/7.5.5 (qtver=7.5.5;os=Windows NT 5.1Service Pack 3)
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 5
|
|
Session: C85B60A2961D9DE3AC08
|
|
|
|
PLAY rtsp://192.168.68.236:554/file/2009-12-14.avi RTSP/1.0
|
|
CSeq: 6
|
|
Range: npt=8.753333-
|
|
x-prebuffer: maxtime=2.000000
|
|
Session: C85B60A2961D9DE3AC08
|
|
User-Agent: QuickTime/7.5.5 (qtver=7.5.5;os=Windows NT 5.1Service Pack 3)
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 6
|
|
Session: C85B60A2961D9DE3AC08
|
|
Range: npt=now-
|
|
RTP-Info: url=rtsp://192.168.68.236:554/file/2009-12-14.avi/trackID=0;seq=10048;rtptime=0,url=rtsp://192.168.68.236:554/file/2009-12-14.avi/trackID=1;seq=2058;rtptime=0
|
|
|
|
PAUSE rtsp://192.168.68.236:554/file/2009-12-14.avi RTSP/1.0
|
|
CSeq: 7
|
|
Session: C85B60A2961D9DE3AC08
|
|
User-Agent: QuickTime/7.5.5 (qtver=7.5.5;os=Windows NT 5.1Service Pack 3)
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 7
|
|
Session: C85B60A2961D9DE3AC08
|
|
|
|
TEARDOWN rtsp://192.168.68.236:554/file/2009-12-14.avi RTSP/1.0
|
|
CSeq: 8
|
|
Session: C85B60A2961D9DE3AC08
|
|
User-Agent: QuickTime/7.5.5 (qtver=7.5.5;os=Windows NT 5.1Service Pack 3)
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 8
|
|
Session: C85B60A2961D9DE3AC08
|
|
|
|
8.
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
1. QT PLAY->PAUSE
|
|
handle_DESCRIBE
|
|
describe the file 'rtsp://192.168.68.236:554/file/2009-12-02.avi'
|
|
handle_SETUP
|
|
handle_SETUP
|
|
handle_PLAY
|
|
play the file 'rtsp://192.168.68.236:554/file/2009-12-02.avi'
|
|
handle_PAUSE
|
|
handle_TEARDOWN
|
|
drop_conn(RTSP)
|
|
drop_conn: ep NULL
|
|
|
|
QT PLAY->QUIT
|
|
handle_DESCRIBE
|
|
describe the file 'rtsp://192.168.68.236:554/file/2009-12-02.avi'
|
|
handle_SETUP
|
|
handle_SETUP
|
|
handle_PLAY
|
|
play the file 'rtsp://192.168.68.236:554/file/2009-12-02.avi'
|
|
handle_PAUSE
|
|
handle_TEARDOWN
|
|
drop_conn(RTSP)
|
|
drop_conn: ep NULL
|
|
|
|
VLC PLAY->PAUSE
|
|
handle_DESCRIBE
|
|
handle_SETUP
|
|
handle_SETUP
|
|
handle_PLAY
|
|
play the file 'rtsp://192.168.68.236:554/file/2009-12-02.avi/'
|
|
|
|
VLC PLAY->STOP
|
|
handle_DESCRIBE
|
|
describe the file 'rtsp://192.168.68.236:554/file/2009-12-02.avi'
|
|
handle_SETUP
|
|
handle_SETUP
|
|
handle_PLAY
|
|
play the file 'rtsp://192.168.68.236:554/file/2009-12-02.avi/'
|
|
handle_TEARDOWN
|
|
before teardown()
|
|
stop the file 'rtsp://192.168.68.236:554/file/2009-12-02.avi/'
|
|
exec_ipc_cmd: GMSS_CMD_DEREG(16)
|
|
drop_conn(RTSP)
|
|
drop_conn: ep NULL
|
|
|
|
VLC PLAY->QUIT
|
|
handle_DESCRIBE
|
|
describe the file 'rtsp://192.168.68.236:554/file/2009-12-02.avi'
|
|
handle_SETUP
|
|
handle_SETUP
|
|
handle_PLAY
|
|
play the file 'rtsp://192.168.68.236:554/file/2009-12-02.avi/'
|
|
handle_TEARDOWN
|
|
before teardown()
|
|
stop the file 'rtsp://192.168.68.236:554/file/2009-12-02.avi/'
|
|
exec_ipc_cmd: GMSS_CMD_DEREG(16)
|
|
drop_conn(RTSP)
|
|
drop_conn: ep NULL
|
|
|
|
rtsp_test PLAY->QUIT
|
|
handle_DESCRIBE
|
|
describe the file 'rtsp://127.0.0.1:554/file/2009-12-02.avi'
|
|
handle_SETUP
|
|
handle_SETUP
|
|
handle_PLAY
|
|
play the file 'rtsp://127.0.0.1:554/file/2009-12-02.avi'
|
|
drop_conn(RTSP)
|
|
drop_conn: live_source 0x9bf6208
|
|
rtsp_conn_disconnect:ichan[0].ep 0x9bf4ee8, rtcp 0
|
|
rtsp_conn_disconnect:ichan[2].ep 0x9b58a68, rtcp 0
|
|
|
|
2.
|
|
PLAY rtsp://192.168.68.236:554/file/20091201.avi RTSP/1.0
|
|
CSeq: 4
|
|
Range: npt=0.000000-
|
|
x-prebuffer: maxtime=2.000000
|
|
Session: E6D2932B527898EF618A
|
|
User-Agent: QuickTime/7.5.5 (qtver=7.5.5;os=Windows NT 5.1Service Pack 3)
|
|
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 4
|
|
Session: E6D2932B527898EF618A
|
|
Range: npt=now-
|
|
RTP-Info: url=rtsp://192.168.68.236:554/file/20091201.avi/trackID=0;seq=25237;rtptime=0,url=rtsp://192.168.68.236:554/file/20091201.avi/trackID=1;seq=5581;rtptime=0
|
|
|
|
|
|
PAUSE rtsp://192.168.68.236:554/file/20091201.avi RTSP/1.0
|
|
CSeq: 5
|
|
Session: E6D2932B527898EF618A
|
|
User-Agent: QuickTime/7.5.5 (qtver=7.5.5;os=Windows NT 5.1Service Pack 3)
|
|
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 5
|
|
Session: E6D2932B527898EF618A
|
|
|
|
|
|
PLAY rtsp://192.168.68.236:554/file/20091201.avi RTSP/1.0
|
|
CSeq: 6
|
|
Range: npt=74.141667-
|
|
x-prebuffer: maxtime=2.000000
|
|
Session: E6D2932B527898EF618A
|
|
User-Agent: QuickTime/7.5.5 (qtver=7.5.5;os=Windows NT 5.1Service Pack 3)
|
|
|
|
|
|
RTSP/1.0 200 OK
|
|
CSeq: 6
|
|
Session: E6D2932B527898EF618A
|
|
Range: npt=74.141667-
|
|
RTP-Info: url=rtsp://192.168.68.236:554/file/20091201.avi/trackID=0;seq=30225,url=rtsp://192.168.68.236:554/file/20091201.avi/trackID=1;seq=6679
|
|
|
|
|
|
|
|
===============================================================================
|
|
|
|
event.c
|
|
static struct event *time_event_list = NULL;
|
|
static struct event *fd_event_list = NULL;
|
|
static struct event *always_event_list = NULL;
|
|
http.c
|
|
static struct http_location *http_loc_list = NULL;
|
|
rtsp.c
|
|
static struct rtsp_location *rtsp_loc_list = NULL;
|
|
static struct rtsp_session *sess_list = NULL;
|
|
session.c
|
|
static struct session *sess_list = NULL;
|
|
stream.c
|
|
static struct stream *stream_list = NULL;
|
|
tcp.c
|
|
struct listener *listener = NULL;
|
|
static struct conn *conn_list = NULL;
|