|
|
@@ -91,6 +91,7 @@ typedef struct RTMPContext { |
|
|
|
char* flashver; ///< version of the flash plugin |
|
|
|
char* swfurl; ///< url of the swf player |
|
|
|
char* pageurl; ///< url of the web page |
|
|
|
char* subscribe; ///< name of live stream to subscribe |
|
|
|
int server_bw; ///< server bandwidth |
|
|
|
int client_buffer_time; ///< client buffer time in ms |
|
|
|
int flush_interval; ///< number of packets flushed in the same request (RTMPT only) |
|
|
@@ -604,21 +605,22 @@ static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts) |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt) |
|
|
|
static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt, |
|
|
|
const char *subscribe) |
|
|
|
{ |
|
|
|
RTMPPacket pkt; |
|
|
|
uint8_t *p; |
|
|
|
int ret; |
|
|
|
|
|
|
|
if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, |
|
|
|
0, 27 + strlen(rt->playpath))) < 0) |
|
|
|
0, 27 + strlen(subscribe))) < 0) |
|
|
|
return ret; |
|
|
|
|
|
|
|
p = pkt.data; |
|
|
|
ff_amf_write_string(&p, "FCSubscribe"); |
|
|
|
ff_amf_write_number(&p, ++rt->nb_invokes); |
|
|
|
ff_amf_write_null(&p); |
|
|
|
ff_amf_write_string(&p, rt->playpath); |
|
|
|
ff_amf_write_string(&p, subscribe); |
|
|
|
|
|
|
|
ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, |
|
|
|
rt->prev_pkt[1]); |
|
|
@@ -1036,9 +1038,15 @@ static int handle_invoke(URLContext *s, RTMPPacket *pkt) |
|
|
|
return ret; |
|
|
|
|
|
|
|
if (rt->is_input) { |
|
|
|
/* Send the FCSubscribe command if live stream. */ |
|
|
|
if (rt->live == -1) { |
|
|
|
if ((ret = gen_fcsubscribe_stream(s, rt)) < 0) |
|
|
|
/* Send the FCSubscribe command when the name of live |
|
|
|
* stream is defined by the user or if it's a live stream. */ |
|
|
|
if (rt->subscribe) { |
|
|
|
if ((ret = gen_fcsubscribe_stream(s, rt, |
|
|
|
rt->subscribe)) < 0) |
|
|
|
return ret; |
|
|
|
} else if (rt->live == -1) { |
|
|
|
if ((ret = gen_fcsubscribe_stream(s, rt, |
|
|
|
rt->playpath)) < 0) |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
@@ -1624,6 +1632,7 @@ static const AVOption rtmp_options[] = { |
|
|
|
{"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {0}, 0, 0, DEC, "rtmp_live"}, |
|
|
|
{"rtmp_pageurl", "URL of the web page in which the media was embedded. By default no value will be sent.", OFFSET(pageurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC}, |
|
|
|
{"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, |
|
|
|
{"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC}, |
|
|
|
{"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, |
|
|
|
{"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, |
|
|
|
{ NULL }, |
|
|
|