121 lines
3.4 KiB
C++
121 lines
3.4 KiB
C++
// RFC-2326 10.6 PAUSE (p36)
|
|
// 1. A PAUSE request discards all queued PLAY requests. However, the pause
|
|
// point in the media stream MUST be maintained. A subsequent PLAY
|
|
// request without Range header resumes from the pause point. (p36)
|
|
// 2. The PAUSE request may contain a Range header specifying when the
|
|
// stream or presentation is to be halted. (p36) (p45 for more)
|
|
|
|
/*
|
|
C->S:
|
|
PAUSE rtsp://example.com/fizzle/foo RTSP/1.0
|
|
CSeq: 834
|
|
Session: 12345678
|
|
|
|
S->C:
|
|
RTSP/1.0 200 OK
|
|
CSeq: 834
|
|
Date: 23 Jan 1997 15:35:06 GMT
|
|
*/
|
|
|
|
#include "rtsp-client.h"
|
|
#include "rtsp-client-internal.h"
|
|
|
|
static const char* sc_format =
|
|
"PAUSE %s RTSP/1.0\r\n"
|
|
"CSeq: %u\r\n"
|
|
"Session: %s\r\n"
|
|
"%s" // Authorization: Digest xxx
|
|
"User-Agent: %s\r\n"
|
|
"\r\n";
|
|
|
|
static int rtsp_client_media_pause(struct rtsp_client_t *rtsp, int i)
|
|
{
|
|
int r;
|
|
assert(0 == rtsp->aggregate);
|
|
assert(i < rtsp->media_count);
|
|
assert(RTSP_PAUSE == rtsp->state);
|
|
if (i >= rtsp->media_count) return -1;
|
|
|
|
assert(rtsp->media[i].uri[0] && rtsp->session[i].session[0]);
|
|
r = rtsp_client_authenrization(rtsp, "PAUSE", rtsp->media[i].uri, NULL, 0, rtsp->authenrization, sizeof(rtsp->authenrization));
|
|
r = snprintf(rtsp->req, sizeof(rtsp->req), sc_format, rtsp->media[i].uri, rtsp->cseq++, rtsp->session[i].session, rtsp->authenrization, USER_AGENT);
|
|
return (r > 0 && r < sizeof(rtsp->req) && r == rtsp->handler.send(rtsp->param, rtsp->media[i].uri, rtsp->req, r)) ? 0 : -1;
|
|
}
|
|
|
|
int rtsp_client_pause(struct rtsp_client_t *rtsp)
|
|
{
|
|
int r;
|
|
assert(RTSP_SETUP == rtsp->state || RTSP_PLAY == rtsp->state || RTSP_PAUSE == rtsp->state);
|
|
rtsp->state = RTSP_PAUSE;
|
|
rtsp->progress = 0;
|
|
|
|
if(rtsp->aggregate)
|
|
{
|
|
assert(rtsp->media_count > 0);
|
|
assert(rtsp->aggregate_uri[0]);
|
|
r = rtsp_client_authenrization(rtsp, "PAUSE", rtsp->aggregate_uri, NULL, 0, rtsp->authenrization, sizeof(rtsp->authenrization));
|
|
r = snprintf(rtsp->req, sizeof(rtsp->req), sc_format, rtsp->aggregate_uri, rtsp->cseq++, rtsp->session[0].session, rtsp->authenrization, USER_AGENT);
|
|
return (r > 0 && r < sizeof(rtsp->req) && r == rtsp->handler.send(rtsp->param, rtsp->aggregate_uri, rtsp->req, r)) ? 0 : -1;
|
|
}
|
|
else
|
|
{
|
|
return rtsp_client_media_pause(rtsp, rtsp->progress);
|
|
}
|
|
}
|
|
|
|
static int rtsp_client_media_pause_onreply(struct rtsp_client_t* rtsp, void* parser)
|
|
{
|
|
int code;
|
|
assert(0 == rtsp->aggregate);
|
|
assert(rtsp->progress < rtsp->media_count);
|
|
|
|
code = http_get_status_code(parser);
|
|
assert(460 != code); // 460 Only aggregate operation allowed (p26)
|
|
if (200 == code)
|
|
{
|
|
if (rtsp->media_count == ++rtsp->progress)
|
|
{
|
|
return rtsp->handler.onpause(rtsp->param);
|
|
}
|
|
else
|
|
{
|
|
return rtsp_client_media_pause(rtsp, rtsp->progress);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// aggregate control reply
|
|
static int rtsp_client_aggregate_pause_onreply(struct rtsp_client_t* rtsp, void* parser)
|
|
{
|
|
int code;
|
|
|
|
assert(rtsp->aggregate);
|
|
code = http_get_status_code(parser);
|
|
if (459 == code) // 459 Aggregate operation not allowed (p26)
|
|
{
|
|
rtsp->aggregate = 0;
|
|
return rtsp_client_media_pause(rtsp, rtsp->progress);
|
|
}
|
|
else if(200 == code)
|
|
{
|
|
return rtsp->handler.onpause(rtsp->param);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int rtsp_client_pause_onreply(struct rtsp_client_t* rtsp, void* parser)
|
|
{
|
|
assert(RTSP_PAUSE == rtsp->state);
|
|
assert(rtsp->progress < rtsp->media_count);
|
|
|
|
if (rtsp->aggregate)
|
|
return rtsp_client_aggregate_pause_onreply(rtsp, parser);
|
|
else
|
|
return rtsp_client_media_pause_onreply(rtsp, parser);
|
|
}
|