diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 48eed561d2..771d31f67a 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -1764,13 +1764,84 @@ static int handle_invoke_error(URLContext *s, RTMPPacket *pkt) return ret; } +static int write_begin(URLContext *s) +{ + RTMPContext *rt = s->priv_data; + PutByteContext pbc; + RTMPPacket spkt = { 0 }; + int ret; + + // Send Stream Begin 1 + if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL, + RTMP_PT_PING, 0, 6)) < 0) { + av_log(s, AV_LOG_ERROR, "Unable to create response packet\n"); + return ret; + } + + bytestream2_init_writer(&pbc, spkt.data, spkt.size); + bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin + bytestream2_put_be32(&pbc, rt->nb_streamid); + + ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size, + rt->prev_pkt[1]); + + ff_rtmp_packet_destroy(&spkt); + + return ret; +} + +static int write_status(URLContext *s, RTMPPacket *pkt, + const char *status, const char *filename) +{ + RTMPContext *rt = s->priv_data; + RTMPPacket spkt = { 0 }; + char statusmsg[128]; + uint8_t *pp; + int ret; + + if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL, + RTMP_PT_INVOKE, 0, + RTMP_PKTDATA_DEFAULT_SIZE)) < 0) { + av_log(s, AV_LOG_ERROR, "Unable to create response packet\n"); + return ret; + } + + pp = spkt.data; + spkt.extra = pkt->extra; + ff_amf_write_string(&pp, "onStatus"); + ff_amf_write_number(&pp, 0); + ff_amf_write_null(&pp); + + ff_amf_write_object_start(&pp); + ff_amf_write_field_name(&pp, "level"); + ff_amf_write_string(&pp, "status"); + ff_amf_write_field_name(&pp, "code"); + ff_amf_write_string(&pp, status); + ff_amf_write_field_name(&pp, "description"); + snprintf(statusmsg, sizeof(statusmsg), + "%s is now published", filename); + ff_amf_write_string(&pp, statusmsg); + ff_amf_write_field_name(&pp, "details"); + ff_amf_write_string(&pp, filename); + ff_amf_write_field_name(&pp, "clientid"); + snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT); + ff_amf_write_string(&pp, statusmsg); + ff_amf_write_object_end(&pp); + + spkt.size = pp - spkt.data; + ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size, + rt->prev_pkt[1]); + ff_rtmp_packet_destroy(&spkt); + + return ret; +} + static int send_invoke_response(URLContext *s, RTMPPacket *pkt) { RTMPContext *rt = s->priv_data; double seqnum; char filename[64]; char command[64]; - char statusmsg[128]; int stringlen; char *pchar; const uint8_t *p = pkt->data; @@ -1823,52 +1894,13 @@ static int send_invoke_response(URLContext *s, RTMPPacket *pkt) pp = spkt.data; ff_amf_write_string(&pp, "onFCPublish"); } else if (!strcmp(command, "publish")) { - PutByteContext pbc; - // Send Stream Begin 1 - if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL, - RTMP_PT_PING, 0, 6)) < 0) { - av_log(s, AV_LOG_ERROR, "Unable to create response packet\n"); - return ret; - } - pp = spkt.data; - bytestream2_init_writer(&pbc, pp, spkt.size); - bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin - bytestream2_put_be32(&pbc, rt->nb_streamid); - ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size, - rt->prev_pkt[1]); - ff_rtmp_packet_destroy(&spkt); + ret = write_begin(s); if (ret < 0) return ret; // Send onStatus(NetStream.Publish.Start) - if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL, - RTMP_PT_INVOKE, 0, - RTMP_PKTDATA_DEFAULT_SIZE)) < 0) { - av_log(s, AV_LOG_ERROR, "Unable to create response packet\n"); - return ret; - } - spkt.extra = pkt->extra; - pp = spkt.data; - ff_amf_write_string(&pp, "onStatus"); - ff_amf_write_number(&pp, 0); - ff_amf_write_null(&pp); - - ff_amf_write_object_start(&pp); - ff_amf_write_field_name(&pp, "level"); - ff_amf_write_string(&pp, "status"); - ff_amf_write_field_name(&pp, "code"); - ff_amf_write_string(&pp, "NetStream.Publish.Start"); - ff_amf_write_field_name(&pp, "description"); - snprintf(statusmsg, sizeof(statusmsg), - "%s is now published", filename); - ff_amf_write_string(&pp, statusmsg); - ff_amf_write_field_name(&pp, "details"); - ff_amf_write_string(&pp, filename); - ff_amf_write_field_name(&pp, "clientid"); - snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT); - ff_amf_write_string(&pp, statusmsg); - ff_amf_write_object_end(&pp); - + return write_status(s, pkt, "NetStream.Publish.Start", + filename); } else { if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,