On Tue, May 15, 2012 at 3:22 AM, Luca Barbato <[email protected]> wrote:
> From: Samuel Pitoiset <[email protected]> > > Allow using connection parameters in order to append arbitrary > AMF data like "B:1 S:authMe O:1 NN:code:1.23 NS:flag:ok O:0" to the > Connect message. > > Signed-off-by: Luca Barbato <[email protected]> > --- > > Eventually I had time to test it, Samuel you need to update the pointer > when you use ff_amf_write_* so your connection argument were dropped. > Please remember that the next time. > Okay, thanks. I understood what was wrong. > doc/protocols.texi | 10 ++++++ > libavformat/rtmpproto.c | 76 > +++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 86 insertions(+), 0 deletions(-) > > diff --git a/doc/protocols.texi b/doc/protocols.texi > index 9ac5151..d69808d 100644 > --- a/doc/protocols.texi > +++ b/doc/protocols.texi > @@ -185,6 +185,16 @@ the path where the application is installed on the > RTMP server > It is the path or name of the resource to play with reference to the > application specified in @var{app}, may be prefixed by "mp4:". > > +@item conn > +It is the connection parameters used to append arbitrary AMF data. > +The type must be B for Boolean, N for number, S for string, O for > +object, or Z for null. For Booleans the data must be either 0 or 1 for > +FALSE or TRUE, respectively. Likewise for Objects the data must be > +0 or 1 to end or begin an object, respectively. Data items in subobjects > +may be named, by prefixing the type with 'N' and specifying the name > +before the value (ie. NB:myFlag:1). This option may be used multiple times > +to construct arbitrary AMF sequences. > + > @end table > > For example to read with @file{avplay} a multimedia resource named > diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c > index f2b417c..2f7d17d 100644 > --- a/libavformat/rtmpproto.c > +++ b/libavformat/rtmpproto.c > @@ -70,6 +70,7 @@ typedef struct RTMPContext { > char *playpath; ///< stream identifier to > play (with possible "mp4:" prefix) > int live; ///< 0: recorded, -1: live, > -2: both > char *app; ///< name of application > + char *conn; ///< arbitrary AMF data > ClientState state; ///< current state > int main_channel_id; ///< an additional channel > ID which is used for some invocations > uint8_t* flv_data; ///< buffer with data for > demuxer > @@ -112,6 +113,65 @@ static const uint8_t rtmp_server_key[] = { > 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE > }; > > +static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p) > +{ > + char *field, *value, *saveptr; > + char type; > + > + /* The type must be B for Boolean, N for number, S for string, O for > + * object, or Z for null. For Booleans the data must be either 0 or 1 > for > + * FALSE or TRUE, respectively. Likewise for Objects the data must be > + * 0 or 1 to end or begin an object, respectively. Data items in > subobjects > + * may be named, by prefixing the type with 'N' and specifying the > name > + * before the value (ie. NB:myFlag:1). This option may be used > multiple times > + * to construct arbitrary AMF sequences. */ > + if (param[1] == ':') { > + type = param[0]; > + value = param + 2; > + } else if (param[0] == 'N' && param[2] == ':') { > + type = param[1]; > + field = strtok_r(param + 3, ":", &saveptr); > + value = strtok_r(NULL, ":", &saveptr); > + > + if (!field || !value) > + goto fail; > + > + ff_amf_write_field_name(p, field); > + } else { > + goto fail; > + } > + > + switch (type) { > + case 'B': > + ff_amf_write_bool(p, value[0] != '0'); > + break; > + case 'S': > + ff_amf_write_string(p, value); > + break; > + case 'N': > + ff_amf_write_number(p, strtod(value, NULL)); > + break; > + case 'Z': > + ff_amf_write_null(p); > + break; > + case 'O': > + if (value[0] != '0') > + ff_amf_write_object_start(p); > + else > + ff_amf_write_object_end(p); > + break; > + default: > + goto fail; > + break; > + } > + > + return 0; > + > +fail: > + av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param); > + return AVERROR(EINVAL); > +} > + > /** > * Generate 'connect' call and send it to the server. > */ > @@ -161,6 +221,21 @@ static void gen_connect(URLContext *s, RTMPContext > *rt) > } > ff_amf_write_object_end(&p); > > + if (rt->conn) { > + char *param, *saveptr; > + > + // Write arbitrary AMF data to the Connect message. > + param = strtok_r(rt->conn, " ", &saveptr); > + while (param != NULL) { > + if (rtmp_write_amf_data(s, param, &p) < 0) { > + // Invalid AMF parameter. > + break; > + } > + > + param = strtok_r(NULL, " ", &saveptr); > + } > + } > + > pkt.data_size = p - pkt.data; > > ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, > rt->prev_pkt[1]); > @@ -1103,6 +1178,7 @@ static const AVOption rtmp_options[] = { > {"rtmp_playpath", "Stream identifier to play or to publish", > OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, > {"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 > rtmp://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL > }, 0, 0, DEC|ENC}, > + {"rtmp_conn", "Append arbitrary AMF data to the Connect message", > OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC}, > { NULL }, > }; > > -- > 1.7.8.rc1 > > _______________________________________________ > libav-devel mailing list > [email protected] > https://lists.libav.org/mailman/listinfo/libav-devel > -- Best regards, Samuel Pitoiset.
_______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
