mirror of
https://github.com/albfan/miraclecast.git
synced 2025-03-09 23:38:56 +00:00
miracle-wfdctl: finish migration of source side rtsp protocol
This commit is contained in:
parent
3bcb8f51f6
commit
9dd805378e
5 changed files with 428 additions and 200 deletions
|
@ -162,7 +162,7 @@ enum wfd_session_state
|
|||
{
|
||||
WFD_SESSION_STATE_NULL,
|
||||
WFD_SESSION_STATE_CONNECTING,
|
||||
WFD_SESSION_STATE_CAPS_EXCHAING,
|
||||
WFD_SESSION_STATE_CAPS_EXCHANGING,
|
||||
WFD_SESSION_STATE_ESTABLISHED,
|
||||
WFD_SESSION_STATE_SETING_UP,
|
||||
WFD_SESSION_STATE_PLAYING,
|
||||
|
@ -174,7 +174,7 @@ int wfd_out_session_new(struct wfd_session **out, struct wfd_sink *sink);
|
|||
int wfd_session_start(struct wfd_session *s, uint64_t id);
|
||||
enum wfd_session_dir wfd_session_get_dir(struct wfd_session *s);
|
||||
uint64_t wfd_session_get_id(struct wfd_session *s);
|
||||
const char * wfd_session_get_url(struct wfd_session *s);
|
||||
const char * wfd_session_get_stream_url(struct wfd_session *s);
|
||||
enum wfd_session_state wfd_session_get_state(struct wfd_session *s);
|
||||
int wfd_session_is_started(struct wfd_session *s);
|
||||
void wfd_session_end(struct wfd_session *s);
|
||||
|
|
|
@ -489,7 +489,7 @@ static int wfd_dbus_session_get_sink(sd_bus *bus,
|
|||
return sd_bus_message_append(reply, "o", sink_path);
|
||||
}
|
||||
|
||||
static int wfd_dbus_session_get_url(sd_bus *bus,
|
||||
static int wfd_dbus_get_session_presentation_url(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
|
@ -498,10 +498,12 @@ static int wfd_dbus_session_get_url(sd_bus *bus,
|
|||
sd_bus_error *ret_error)
|
||||
{
|
||||
struct wfd_session *s = userdata;
|
||||
return sd_bus_message_append(reply, "s", wfd_session_get_url(s));
|
||||
return sd_bus_message_append(reply,
|
||||
"s",
|
||||
wfd_session_get_stream_url(s));
|
||||
}
|
||||
|
||||
static int wfd_dbus_session_get_state(sd_bus *bus,
|
||||
static int wfd_dbus_get_session_state(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
|
@ -554,8 +556,8 @@ static const sd_bus_vtable wfd_dbus_session_vtable[] = {
|
|||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_METHOD("End", NULL, NULL, wfd_dbus_session_end, 0),
|
||||
SD_BUS_PROPERTY("Sink", "o", wfd_dbus_session_get_sink, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Url", "o", wfd_dbus_session_get_url, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("State", "i", wfd_dbus_session_get_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Url", "o", wfd_dbus_get_session_presentation_url, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("State", "i", wfd_dbus_get_session_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_VTABLE_END,
|
||||
};
|
||||
|
||||
|
|
|
@ -186,67 +186,104 @@ static int wfd_out_session_initiate_request(struct wfd_session *s)
|
|||
return wfd_session_request(s, RTSP_M1_REQUEST_SINK_OPTIONS);
|
||||
}
|
||||
|
||||
/*static int wfd_out_session_handle_get_parameter_reply(struct rtsp *bus,*/
|
||||
/*struct rtsp_message *m,*/
|
||||
/*void *userdata)*/
|
||||
/*{*/
|
||||
/*struct wfd_session *s = userdata;*/
|
||||
static int wfd_out_session_handle_get_parameter_reply(struct wfd_session *s,
|
||||
struct rtsp_message *m,
|
||||
enum wfd_session_state *new_state,
|
||||
enum rtsp_message_id *next_request)
|
||||
{
|
||||
struct wfd_video_formats *vformats;
|
||||
struct wfd_audio_codecs *acodecs;
|
||||
uint16_t rtp_ports[2];
|
||||
_shl_free_ char *t = NULL;
|
||||
const char *l;
|
||||
int r;
|
||||
|
||||
/*log_debug("received GET_PARAMETER reply (M3): %s\n",*/
|
||||
/*(char *) rtsp_message_get_raw(m));*/
|
||||
/*if(RTSP_CODE_OK != rtsp_message_get_code(m)) {*/
|
||||
/*wfd_session_end(wfd_session(userdata));*/
|
||||
/*return -EPROTO;*/
|
||||
/*}*/
|
||||
if(!rtsp_message_read(m, "{<&>}", "wfd_video_formats", &l)) {
|
||||
r = wfd_video_formats_from_string(l, &vformats);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/*return 0;*/
|
||||
/*}*/
|
||||
if(s->vformats) {
|
||||
free(s->vformats);
|
||||
}
|
||||
s->vformats = vformats;
|
||||
}
|
||||
|
||||
/*static int wfd_out_session_send_get_parameter(sd_event_source *source,*/
|
||||
/*void *userdata)*/
|
||||
/*{*/
|
||||
/*struct wfd_session *s = userdata;*/
|
||||
/*_rtsp_message_unref_ struct rtsp_message *m = NULL;*/
|
||||
/*int r = rtsp_message_new_request(s->rtsp,*/
|
||||
/*&m,*/
|
||||
/*"GET_PARAMETER",*/
|
||||
/*s->url);*/
|
||||
/*if (0 > r) {*/
|
||||
/*goto error;*/
|
||||
/*}*/
|
||||
if(!rtsp_message_read(m, "{<&>}", "wfd_audio_codecs", &l)) {
|
||||
r = wfd_audio_codecs_from_string(l, &acodecs);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if(s->acodecs) {
|
||||
free(s->acodecs);
|
||||
}
|
||||
s->acodecs = acodecs;
|
||||
}
|
||||
|
||||
/*r = rtsp_message_append(m, "{&}",*/
|
||||
/*"wfd_video_formats\n"*/
|
||||
/*"wfd_audio_codecs\n"*/
|
||||
/*"wfd_client_rtp_ports"*/
|
||||
/*//"wfd_uibc_capability"*/
|
||||
/*);*/
|
||||
/*if (0 > r) {*/
|
||||
/*goto error;*/
|
||||
/*}*/
|
||||
if(!rtsp_message_read(m, "{<&>}", "wfd_client_rtp_ports", &l)) {
|
||||
if(strncmp("RTP/AVP/UDP;unicast", l, 19)) {
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
/*rtsp_message_seal(m);*/
|
||||
r = sscanf(l + 20, "%hd %hd %ms",
|
||||
&rtp_ports[0],
|
||||
&rtp_ports[1],
|
||||
&t);
|
||||
if(3 != r) {
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
/*r = rtsp_call_async(s->rtsp,*/
|
||||
/*m,*/
|
||||
/*wfd_out_session_handle_get_parameter_reply,*/
|
||||
/*s,*/
|
||||
/*0,*/
|
||||
/*NULL);*/
|
||||
/*if (r < 0) {*/
|
||||
/*goto error;*/
|
||||
/*}*/
|
||||
if(strncmp("mode=play", t, 9)) {
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
/*log_debug("Sending GET_PARAMETER (M3): %s\n",*/
|
||||
/*(char *) rtsp_message_get_raw(m));*/
|
||||
if(!rtp_ports[0] && !rtp_ports[1]) {
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
/*return 0;*/
|
||||
s->rtp_ports[0] = rtp_ports[0];
|
||||
s->rtp_ports[1] = rtp_ports[1];
|
||||
}
|
||||
|
||||
/*error:*/
|
||||
/*wfd_session_end(s);*/
|
||||
*next_request = RTSP_M4_SET_PARAMETER;
|
||||
|
||||
/*return r;*/
|
||||
/*}*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wfd_out_session_request_get_parameter(struct wfd_session *s,
|
||||
struct rtsp_message **out)
|
||||
{
|
||||
_rtsp_message_unref_ struct rtsp_message *m = NULL;
|
||||
int r = rtsp_message_new_request(s->rtsp,
|
||||
&m,
|
||||
"GET_PARAMETER",
|
||||
"rtsp://localhost/wfd1.0");
|
||||
if (0 > r) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = rtsp_message_append(m, "{&}",
|
||||
"wfd_video_formats\n"
|
||||
"wfd_audio_codecs\n"
|
||||
"wfd_client_rtp_ports"
|
||||
//"wfd_uibc_capability"
|
||||
);
|
||||
if (0 > r) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
*out = m;
|
||||
m = NULL;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
wfd_session_end(s);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool find_strv(const char *str, char **strv)
|
||||
{
|
||||
|
@ -262,7 +299,9 @@ static bool find_strv(const char *str, char **strv)
|
|||
|
||||
static int wfd_out_session_handle_options_request(struct wfd_session *s,
|
||||
struct rtsp_message *req,
|
||||
struct rtsp_message **out_rep)
|
||||
struct rtsp_message **out_rep,
|
||||
enum wfd_session_state *new_state,
|
||||
enum rtsp_message_id *next_request)
|
||||
{
|
||||
const char *require;
|
||||
_rtsp_message_unref_ struct rtsp_message *rep = NULL;
|
||||
|
@ -298,11 +337,15 @@ static int wfd_out_session_handle_options_request(struct wfd_session *s,
|
|||
*out_rep = rep;
|
||||
rep = NULL;
|
||||
|
||||
*next_request = RTSP_M3_GET_PARAMETER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wfd_out_session_check_options_reply(struct wfd_session *s,
|
||||
struct rtsp_message *m)
|
||||
static int wfd_out_session_handle_options_reply(struct wfd_session *s,
|
||||
struct rtsp_message *m,
|
||||
enum wfd_session_state *new_state,
|
||||
enum rtsp_message_id *next_request)
|
||||
{
|
||||
int r;
|
||||
const char *public;
|
||||
|
@ -356,102 +399,198 @@ static int wfd_out_session_request_options(struct wfd_session *s,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*static int wfd_out_session_handle_options_request(struct rtsp *bus,*/
|
||||
/*struct rtsp_message *request,*/
|
||||
/*struct wfd_session *s)*/
|
||||
/*{*/
|
||||
/*}*/
|
||||
|
||||
static int wfd_out_session_handle_play_reply(struct rtsp *bus,
|
||||
struct rtsp_message *m,
|
||||
void *userdata)
|
||||
static int wfd_out_session_handle_play_request(struct wfd_session *s,
|
||||
struct rtsp_message *req,
|
||||
struct rtsp_message **out_rep,
|
||||
enum wfd_session_state *new_state,
|
||||
enum rtsp_message_id *next_request)
|
||||
{
|
||||
/*struct wfd_session *s = userdata;*/
|
||||
/*log_trace("received SETUP (M5) reply: %s",*/
|
||||
/*(char *) rtsp_message_get_raw(m));*/
|
||||
|
||||
/*wfd_out_session_send_play(s);*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wfd_out_session_send_play(struct wfd_session *s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wfd_out_session_handle_setup_reply(struct rtsp *bus,
|
||||
struct rtsp_message *m,
|
||||
void *userdata)
|
||||
{
|
||||
/*struct wfd_session *s = userdata;*/
|
||||
/*log_trace("received SETUP (M5) reply: %s",*/
|
||||
/*(char *) rtsp_message_get_raw(m));*/
|
||||
|
||||
/*wfd_out_session_send_play(s);*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wfd_out_session_handle_set_parameter_reply(struct rtsp *bus,
|
||||
struct rtsp_message *m,
|
||||
void *userdata)
|
||||
{
|
||||
/*struct wfd_session *s = userdata;*/
|
||||
/*log_trace("received SET_PARAMETER (M4) reply: %s",*/
|
||||
/*(char *) rtsp_message_get_raw(m));*/
|
||||
|
||||
/*wfd_out_session_send_setup(s);*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wfd_out_session_send_set_parameter_request(struct wfd_session *s)
|
||||
{
|
||||
/*_rtsp_message_unref_ struct rtsp_message *req;*/
|
||||
_rtsp_message_unref_ struct rtsp_message *m = NULL;
|
||||
int r;
|
||||
/*const static char tmp[] =*/
|
||||
/*"wfd_video_formats: 38 00 02 10 00000080 00000000 00000000 00 0000 0000 11 none none\n"*/
|
||||
/*//"wfd_audio_codecs: AAC 00000001 00\n"*/
|
||||
/*//"wfd_uibc_capability: input_category_list=GENERIC\n;generic_cap_list=SingleTouch;hidc_cap_list=none;port=5100\n"*/
|
||||
/*//"wfd_uibc_setting: disable\n"*/
|
||||
/*"wfd_presentation_URL: %s/streamid=0 none\n"*/
|
||||
/*"wfd_client_rtp_ports: %s %d %d mode=play";*/
|
||||
|
||||
/*r = rtsp_message_new_request(s->rtsp,*/
|
||||
/*&req,*/
|
||||
/*"SET_PARAMETER",*/
|
||||
/*s->url);*/
|
||||
/*if (r < 0) {*/
|
||||
/*cli_vERR(r);*/
|
||||
/*goto error;*/
|
||||
/*}*/
|
||||
r = rtsp_message_new_reply_for(req,
|
||||
&m,
|
||||
RTSP_CODE_OK,
|
||||
NULL);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = rtsp_message_append(m, "<u>", "Session", (uint32_t) s->id);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/*snprintf(buf, sizeof(buf), tmp, s->url, s->sink.rtp_ports.profile,*/
|
||||
/*s->sink.rtp_ports.port0, s->sink.rtp_ports.port1);*/
|
||||
*out_rep = m;
|
||||
m = NULL;
|
||||
|
||||
/*r = rtsp_message_append(req, "{&}", buf);*/
|
||||
/*if (r < 0) {*/
|
||||
/*cli_vERR(r);*/
|
||||
/*goto error;*/
|
||||
/*}*/
|
||||
*new_state = WFD_SESSION_STATE_PLAYING;
|
||||
|
||||
/*rtsp_message_seal(req);*/
|
||||
/*cli_debug("OUTGOING (M4): %s\n", rtsp_message_get_raw(req));*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*r = rtsp_call_async(s->rtsp, req, src_set_parameter_rep_fn, s, 0, NULL);*/
|
||||
/*if (r < 0) {*/
|
||||
/*cli_vERR(r);*/
|
||||
/*goto error;*/
|
||||
/*}*/
|
||||
static int wfd_out_session_handle_setup_request(struct wfd_session *s,
|
||||
struct rtsp_message *req,
|
||||
struct rtsp_message **out_rep,
|
||||
enum wfd_session_state *new_state,
|
||||
enum rtsp_message_id *next_request)
|
||||
{
|
||||
int r;
|
||||
const char *l;
|
||||
_rtsp_message_unref_ struct rtsp_message *m = NULL;
|
||||
_shl_free_ char *sess = NULL, *trans = NULL;
|
||||
|
||||
/*return 0;*/
|
||||
r = rtsp_message_read(req, "<s>", "Transport", &l);
|
||||
if(0 > r) {
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
/*error:*/
|
||||
/*wfd_src_close(s);*/
|
||||
/*wfd_fn_src_disconnected(s);*/
|
||||
if(strncmp("RTP/AVP/UDP;unicast;", l, 20)) {
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
return r;
|
||||
l += 20;
|
||||
|
||||
if(strncmp("client_port=", l, 12)) {
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
l += 12;
|
||||
|
||||
errno = 0;
|
||||
s->stream.rtp_port = strtoul(l, NULL, 10);
|
||||
if(errno) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
r = rtsp_message_new_reply_for(req,
|
||||
&m,
|
||||
RTSP_CODE_OK,
|
||||
NULL);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = asprintf(&sess, "%" PRIu64 ";timeout=30", s->id);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = rtsp_message_append(m, "<&>", "Session", sess);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = asprintf(&trans, "RTP/AVP/UDP;unicast;client_port=%hd",
|
||||
s->stream.rtp_port);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = rtsp_message_append(m, "<&>", "Transport", trans);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
*out_rep = m;
|
||||
m = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wfd_out_session_request_trigger(struct wfd_session *s,
|
||||
struct rtsp_message **out)
|
||||
{
|
||||
_rtsp_message_unref_ struct rtsp_message *m = NULL;
|
||||
int r;
|
||||
|
||||
switch(wfd_session_get_state(s)) {
|
||||
case WFD_SESSION_STATE_ESTABLISHED:
|
||||
r = rtsp_message_new_request(s->rtsp,
|
||||
&m,
|
||||
"SET_PARAMETER",
|
||||
wfd_session_get_stream_url(s));
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = rtsp_message_append(m, "{<s>}",
|
||||
"wfd_trigger_method",
|
||||
"SETUP");
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(m) {
|
||||
*out = m;
|
||||
m = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wfd_out_session_handle_set_parameter_reply(struct wfd_session *s,
|
||||
struct rtsp_message *m,
|
||||
enum wfd_session_state *new_state,
|
||||
enum rtsp_message_id *next_request)
|
||||
{
|
||||
*new_state = WFD_SESSION_STATE_ESTABLISHED;
|
||||
*next_request = RTSP_M5_TRIGGER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wfd_out_session_request_set_parameter(struct wfd_session *s,
|
||||
struct rtsp_message **out)
|
||||
{
|
||||
_rtsp_message_unref_ struct rtsp_message *m;
|
||||
_shl_free_ char *body = NULL;
|
||||
int r;
|
||||
|
||||
r = wfd_session_gen_stream_url(s,
|
||||
wfd_out_session(s)->sink->peer->local_address,
|
||||
WFD_STREAM_ID_PRIMARY);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
s->stream.id = WFD_STREAM_ID_PRIMARY;
|
||||
|
||||
r = asprintf(&body,
|
||||
"wfd_video_formats: 38 00 02 10 00000080 00000000 00000000 00 0000 0000 11 none none\n"
|
||||
"wfd_audio_codecs: AAC 00000001 00\n"
|
||||
"wfd_presentation_URL: %s none\n"
|
||||
"wfd_client_rtp_ports: %u %u mode=play",
|
||||
//"wfd_uibc_capability: input_category_list=GENERIC\n;generic_cap_list=SingleTouch;hidc_cap_list=none;port=5100\n"
|
||||
//"wfd_uibc_setting: disable\n",
|
||||
wfd_session_get_stream_url(s),
|
||||
s->rtp_ports[0],
|
||||
s->rtp_ports[1]);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = rtsp_message_new_request(s->rtsp,
|
||||
&m,
|
||||
"SET_PARAMETER",
|
||||
"rtsp://localhost/wfd1.0");
|
||||
if (0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = rtsp_message_append(m, "{&}", body);
|
||||
if (0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
*out = m;
|
||||
m = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct wfd_session_vtable session_vtables[] = {
|
||||
|
@ -467,20 +606,27 @@ const struct wfd_session_vtable session_vtables[] = {
|
|||
static const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[] = {
|
||||
[RTSP_M1_REQUEST_SINK_OPTIONS] = {
|
||||
.request = wfd_out_session_request_options,
|
||||
.handle_reply = wfd_out_session_check_options_reply
|
||||
.handle_reply = wfd_out_session_handle_options_reply
|
||||
},
|
||||
[RTSP_M2_REQUEST_SRC_OPTIONS] = {
|
||||
.handle_request = wfd_out_session_handle_options_request
|
||||
},
|
||||
[RTSP_M3_GET_PARAMETER] = {
|
||||
.request = wfd_out_session_request_get_parameter,
|
||||
.handle_reply = wfd_out_session_handle_get_parameter_reply
|
||||
},
|
||||
[RTSP_M4_SET_PARAMETER] = {
|
||||
.request = wfd_out_session_request_set_parameter,
|
||||
.handle_reply = wfd_out_session_handle_set_parameter_reply
|
||||
},
|
||||
[RTSP_M5_TRIGGER] = {
|
||||
.request = wfd_out_session_request_trigger,
|
||||
},
|
||||
[RTSP_M6_SETUP] = {
|
||||
.handle_request = wfd_out_session_handle_setup_request,
|
||||
},
|
||||
[RTSP_M7_PLAY] = {
|
||||
.handle_request = wfd_out_session_handle_play_request,
|
||||
},
|
||||
[RTSP_M8_TEARDOWN] = {
|
||||
},
|
||||
|
|
|
@ -18,14 +18,19 @@
|
|||
*/
|
||||
#define LOG_SUBSYSTEM "wfd-session"
|
||||
|
||||
#include "ctl.h"
|
||||
#include "rtsp.h"
|
||||
#include "wfd-dbus.h"
|
||||
#include "wfd-session.h"
|
||||
#include "shl_macro.h"
|
||||
|
||||
#define rtsp_message_id_is_valid(id) ( \
|
||||
(id) >= RTSP_M1_REQUEST_SINK_OPTIONS && \
|
||||
(id) <= RTSP_M16_KEEPALIVE \
|
||||
#define rtsp_message_id_is_valid(_id) ( \
|
||||
(_id) >= RTSP_M1_REQUEST_SINK_OPTIONS && \
|
||||
(_id) <= RTSP_M16_KEEPALIVE \
|
||||
)
|
||||
#define wfd_stream_id_is_valid(_id) ( \
|
||||
(_id) >= WFD_STREAM_ID_PRIMARY && \
|
||||
(_id) <= WFD_STREAM_ID_SECONDARY \
|
||||
)
|
||||
|
||||
static const char *rtsp_message_names[];
|
||||
|
@ -47,26 +52,37 @@ static inline int wfd_session_do_request(struct wfd_session *s,
|
|||
static inline int wfd_session_do_handle_request(struct wfd_session *s,
|
||||
enum rtsp_message_id id,
|
||||
struct rtsp_message *req,
|
||||
struct rtsp_message **out_rep)
|
||||
struct rtsp_message **out_rep,
|
||||
enum wfd_session_state *new_state,
|
||||
enum rtsp_message_id *next_request)
|
||||
{
|
||||
if(!rtsp_message_id_is_valid(id)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
assert(s->rtsp_disp_tbl[id].handle_request);
|
||||
|
||||
return (*s->rtsp_disp_tbl[id].handle_request)(s, req, out_rep);
|
||||
return (*s->rtsp_disp_tbl[id].handle_request)(s,
|
||||
req,
|
||||
out_rep,
|
||||
new_state,
|
||||
next_request);
|
||||
}
|
||||
|
||||
static inline int wfd_session_do_handle_reply(struct wfd_session *s,
|
||||
enum rtsp_message_id id,
|
||||
struct rtsp_message *m)
|
||||
struct rtsp_message *m,
|
||||
enum wfd_session_state *new_state,
|
||||
enum rtsp_message_id *next_request)
|
||||
{
|
||||
if(!rtsp_message_id_is_valid(id)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
assert(s->rtsp_disp_tbl[id].handle_reply);
|
||||
|
||||
if(!s->rtsp_disp_tbl[id].handle_reply) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (*s->rtsp_disp_tbl[id].handle_reply)(s, m);
|
||||
return (*s->rtsp_disp_tbl[id].handle_reply)(s, m, new_state, next_request);
|
||||
}
|
||||
|
||||
uint64_t wfd_session_get_id(struct wfd_session *s)
|
||||
|
@ -115,12 +131,18 @@ void wfd_session_end(struct wfd_session *s)
|
|||
s->rtsp = NULL;
|
||||
}
|
||||
|
||||
if(s->url) {
|
||||
free(s->url);
|
||||
s->url = NULL;
|
||||
}
|
||||
wfd_video_formats_free(s->vformats);
|
||||
s->vformats = NULL;
|
||||
wfd_audio_codecs_free(s->acodecs);
|
||||
s->acodecs = NULL;
|
||||
|
||||
free(s->stream.url);
|
||||
s->stream.url = NULL;
|
||||
|
||||
s->last_request = RTSP_M_UNKNOWN;
|
||||
wfd_session_set_state(s, WFD_SESSION_STATE_NULL);
|
||||
s->rtp_ports[0] = 0;
|
||||
s->rtp_ports[1] = 0;
|
||||
|
||||
if(wfd_is_out_session(s)) {
|
||||
wfd_fn_out_session_ended(s);
|
||||
|
@ -149,11 +171,6 @@ enum wfd_session_dir wfd_session_get_dir(struct wfd_session *s)
|
|||
return s->dir;
|
||||
}
|
||||
|
||||
const char * wfd_session_get_url(struct wfd_session *s)
|
||||
{
|
||||
return s->url;
|
||||
}
|
||||
|
||||
uint64_t * wfd_session_to_htable(struct wfd_session *s)
|
||||
{
|
||||
return &s->id;
|
||||
|
@ -164,13 +181,27 @@ struct wfd_session * wfd_session_from_htable(uint64_t *e)
|
|||
return shl_htable_entry(e, struct wfd_session, id);
|
||||
}
|
||||
|
||||
static int wfd_session_set_url(struct wfd_session *s, const char *addr)
|
||||
const char * wfd_session_get_stream_url(struct wfd_session *s)
|
||||
{
|
||||
return s->stream.url;
|
||||
}
|
||||
|
||||
int wfd_session_gen_stream_url(struct wfd_session *s,
|
||||
const char *local_addr,
|
||||
enum wfd_stream_id id)
|
||||
{
|
||||
char *url;
|
||||
int r = asprintf(&url, "rtsp://%s/wfd1.0", addr);
|
||||
int r;
|
||||
|
||||
if(!wfd_stream_id_is_valid(id)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = asprintf(&url, "rtsp://%s/wfd1.0/streamid=%d", local_addr, id);
|
||||
if(0 <= r) {
|
||||
free(s->url);
|
||||
s->url = url;
|
||||
free(s->stream.url);
|
||||
s->stream.url = url;
|
||||
url = NULL;
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -206,7 +237,7 @@ static enum rtsp_message_id wfd_session_message_to_id(struct wfd_session *s,
|
|||
return RTSP_M13_REQUEST_IDR;
|
||||
}
|
||||
|
||||
if(0 >= rtsp_message_read(m, "{<>}", "wfd_uibc_capability") && s->url) {
|
||||
if(0 >= rtsp_message_read(m, "{<>}", "wfd_uibc_capability")) { // && s->url) {
|
||||
return RTSP_M14_ESTABLISH_UIBC;
|
||||
}
|
||||
|
||||
|
@ -214,7 +245,7 @@ static enum rtsp_message_id wfd_session_message_to_id(struct wfd_session *s,
|
|||
return RTSP_M15_ENABLE_UIBC;
|
||||
}
|
||||
|
||||
if(!s->url) {
|
||||
if(WFD_SESSION_STATE_CAPS_EXCHANGING == s->state) {
|
||||
return RTSP_M4_SET_PARAMETER;
|
||||
}
|
||||
|
||||
|
@ -253,65 +284,79 @@ static enum rtsp_message_id wfd_session_message_to_id(struct wfd_session *s,
|
|||
return RTSP_M_UNKNOWN;
|
||||
}
|
||||
|
||||
static int wfd_session_dispatch_request(struct rtsp *bus,
|
||||
static int wfd_session_handle_request(struct rtsp *bus,
|
||||
struct rtsp_message *m,
|
||||
void *userdata)
|
||||
{
|
||||
_rtsp_message_unref_ struct rtsp_message *rep = NULL;
|
||||
struct wfd_session *s = userdata;
|
||||
enum rtsp_message_id id;
|
||||
enum rtsp_message_id id, next_request = RTSP_M_UNKNOWN;
|
||||
enum wfd_session_state new_state = WFD_SESSION_STATE_NULL;
|
||||
int r;
|
||||
|
||||
id = wfd_session_message_to_id(s, m);
|
||||
if(RTSP_M_UNKNOWN == id) {
|
||||
r = -EPROTO;
|
||||
goto end;
|
||||
goto error;
|
||||
}
|
||||
|
||||
log_trace("received %s (M%d) request: %s", rtsp_message_id_to_string(id),
|
||||
id,
|
||||
(char *) rtsp_message_get_raw(m));
|
||||
|
||||
r = wfd_session_do_handle_request(s, id, m, &rep);
|
||||
r = wfd_session_do_handle_request(s,
|
||||
id,
|
||||
m,
|
||||
&rep,
|
||||
&new_state,
|
||||
&next_request);
|
||||
if(0 > r) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
r = rtsp_message_set_cookie(rep, id);
|
||||
if(0 > r) {
|
||||
goto end;
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = rtsp_message_seal(rep);
|
||||
if(0 > r) {
|
||||
goto end;
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = rtsp_send(bus, rep);
|
||||
if(0 > r) {
|
||||
goto end;
|
||||
goto error;
|
||||
}
|
||||
|
||||
log_trace("sending %s (M%d) reply: %s", rtsp_message_id_to_string(id),
|
||||
id,
|
||||
(char *) rtsp_message_get_raw(rep));
|
||||
|
||||
end:
|
||||
if (0 > r) {
|
||||
wfd_session_end(s);
|
||||
if(WFD_SESSION_STATE_NULL != new_state) {
|
||||
wfd_session_set_state(s, new_state);
|
||||
}
|
||||
|
||||
if(rtsp_message_id_is_valid(next_request)) {
|
||||
r = wfd_session_request(s, next_request);
|
||||
if(0 > r) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
wfd_session_end(s);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
static int wfd_session_dispatch_reply(struct rtsp *bus,
|
||||
static int wfd_session_handle_reply(struct rtsp *bus,
|
||||
struct rtsp_message *m,
|
||||
void *userdata)
|
||||
{
|
||||
int r;
|
||||
enum rtsp_message_id id;
|
||||
struct wfd_session *s = userdata;
|
||||
enum wfd_session_state new_state = WFD_SESSION_STATE_NULL;
|
||||
enum rtsp_message_id next_request = RTSP_M_UNKNOWN;
|
||||
|
||||
if(!m) {
|
||||
goto error;
|
||||
|
@ -322,18 +367,29 @@ static int wfd_session_dispatch_reply(struct rtsp *bus,
|
|||
goto error;
|
||||
}
|
||||
|
||||
id = (enum rtsp_message_id) rtsp_message_get_cookie(m);
|
||||
id = s->last_request;
|
||||
|
||||
log_trace("received %s (M%d) reply: %s",
|
||||
rtsp_message_id_to_string(id),
|
||||
id,
|
||||
(char *) rtsp_message_get_raw(m));
|
||||
|
||||
r = wfd_session_do_handle_reply(s, id, m);
|
||||
r = wfd_session_do_handle_reply(s, id, m, &new_state, &next_request);
|
||||
if(0 > r) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(WFD_SESSION_STATE_NULL != new_state) {
|
||||
wfd_session_set_state(s, new_state);
|
||||
}
|
||||
|
||||
if(rtsp_message_id_is_valid(next_request)) {
|
||||
r = wfd_session_request(s, next_request);
|
||||
if(0 > r) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
@ -345,7 +401,6 @@ int wfd_session_request(struct wfd_session *s, enum rtsp_message_id id)
|
|||
{
|
||||
int r;
|
||||
_rtsp_message_unref_ struct rtsp_message *m = NULL;
|
||||
uint64_t cookie = id;
|
||||
|
||||
assert(s);
|
||||
|
||||
|
@ -361,14 +416,16 @@ int wfd_session_request(struct wfd_session *s, enum rtsp_message_id id)
|
|||
|
||||
r = rtsp_call_async(s->rtsp,
|
||||
m,
|
||||
wfd_session_dispatch_reply,
|
||||
wfd_session_handle_reply,
|
||||
s,
|
||||
0,
|
||||
&cookie);
|
||||
NULL);
|
||||
if(0 > r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
s->last_request = id;
|
||||
|
||||
log_trace("sending %s (M%d) request: %s",
|
||||
rtsp_message_id_to_string(id),
|
||||
id,
|
||||
|
@ -414,7 +471,7 @@ static int wfd_session_handle_io(sd_event_source *source,
|
|||
goto end;
|
||||
}
|
||||
|
||||
r = rtsp_add_match(rtsp, wfd_session_dispatch_request, s);
|
||||
r = rtsp_add_match(rtsp, wfd_session_handle_request, s);
|
||||
if (0 > r) {
|
||||
goto end;
|
||||
}
|
||||
|
@ -422,7 +479,7 @@ static int wfd_session_handle_io(sd_event_source *source,
|
|||
s->rtsp = rtsp;
|
||||
rtsp = NULL;
|
||||
|
||||
wfd_session_set_state(s, WFD_SESSION_STATE_CAPS_EXCHAING);
|
||||
wfd_session_set_state(s, WFD_SESSION_STATE_CAPS_EXCHANGING);
|
||||
|
||||
r = (*session_vtables[s->dir].initiate_request)(s);
|
||||
}
|
||||
|
|
|
@ -51,16 +51,26 @@ enum rtsp_message_id
|
|||
RTSP_M16_KEEPALIVE,
|
||||
};
|
||||
|
||||
enum wfd_stream_id
|
||||
{
|
||||
WFD_STREAM_ID_PRIMARY,
|
||||
WFD_STREAM_ID_SECONDARY,
|
||||
};
|
||||
|
||||
struct rtsp_dispatch_entry
|
||||
{
|
||||
union {
|
||||
int (*request)(struct wfd_session *s, struct rtsp_message **out);
|
||||
int (*handle_request)(struct wfd_session *s,
|
||||
struct rtsp_message *req,
|
||||
struct rtsp_message **out_rep);
|
||||
struct rtsp_message **out_rep,
|
||||
enum wfd_session_state *new_state,
|
||||
enum rtsp_message_id *next_request);
|
||||
};
|
||||
int (*handle_reply)(struct wfd_session *s, struct rtsp_message *m);
|
||||
enum rtsp_message_id next_request;
|
||||
int (*handle_reply)(struct wfd_session *s,
|
||||
struct rtsp_message *m,
|
||||
enum wfd_session_state *new_state,
|
||||
enum rtsp_message_id *next_request);
|
||||
};
|
||||
|
||||
struct wfd_session_vtable
|
||||
|
@ -76,16 +86,29 @@ struct wfd_session
|
|||
{
|
||||
enum wfd_session_dir dir;
|
||||
enum wfd_session_state state;
|
||||
uint64_t id;
|
||||
char *url;
|
||||
struct rtsp *rtsp;
|
||||
enum rtsp_message_id last_request;
|
||||
const struct rtsp_dispatch_entry *rtsp_disp_tbl;
|
||||
|
||||
uint64_t id;
|
||||
struct rtsp *rtsp;
|
||||
uint16_t rtp_ports[2];
|
||||
struct wfd_video_formats *vformats;
|
||||
struct wfd_audio_codecs *acodecs;
|
||||
|
||||
struct {
|
||||
enum wfd_stream_id id;
|
||||
char *url;
|
||||
uint16_t rtp_port;
|
||||
} stream;
|
||||
|
||||
bool destructed: 1;
|
||||
};
|
||||
|
||||
const char * rtsp_message_id_to_string(enum rtsp_message_id id);
|
||||
struct wfd_sink * wfd_out_session_get_sink(struct wfd_session *s);
|
||||
int wfd_session_request(struct wfd_session *s, enum rtsp_message_id id);
|
||||
int wfd_session_gen_stream_url(struct wfd_session *s,
|
||||
const char *local_addr,
|
||||
enum wfd_stream_id id);
|
||||
|
||||
#endif /* MIRACLE_OUT_SESSION_H */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue