[FFmpeg-devel] [PATCH 5/6] RTMP output: implement rtmp-output
Kostya
kostya.shishkov
Thu Dec 3 17:32:51 CET 2009
On Thu, Dec 03, 2009 at 05:15:08PM +0200, Sergiy wrote:
> Also for handshake with red5, 1st part of server response, received by
> client must be sent back.
[...]
> @@ -163,20 +195,28 @@ static void gen_play(URLContext *s, RTMPContext *rt)
> RTMPPacket pkt;
> uint8_t *p;
>
> - av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
> - ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE, 0,
> - 20 + strlen(rt->playpath));
> + av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Sending %s command for '%s'\n", rt->is_input ? "play" : "publish",
> + rt->playpath);
> + ff_rtmp_packet_create(&pkt, rt->is_input ? RTMP_VIDEO_CHANNEL : RTMP_SOURCE_CHANNEL,
> + RTMP_PT_INVOKE, 0, 4096);
> pkt.extra = rt->main_channel_id;
>
> p = pkt.data;
> + if (rt->is_input)
> ff_amf_write_string(&p, "play");
> + else
> + ff_amf_write_string(&p, "publish");
> ff_amf_write_number(&p, 0.0);
> ff_amf_write_null(&p);
> ff_amf_write_string(&p, rt->playpath);
> + if (!rt->is_input)
> + ff_amf_write_string(&p, "live");
> + pkt.data_size = p - pkt.data;
>
> ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
> ff_rtmp_packet_destroy(&pkt);
>
> + if (rt->is_input) {
> // set client buffer time disguised in ping packet
> ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, 1, 10);
Ahem, sending "publish" instead of "play" in gen_play() is a bit
counterintuitive, don't you think? Make it a separate function instead.
[...]
>
> static int rtmp_write(URLContext *h, uint8_t *buf, int size)
> {
> - return 0;
> + RTMPContext *rt = h->priv_data;
> + int size_temp = size;
> + int pktsize, pkttype;
> + uint32_t ts;
> + const uint8_t *buf_temp = buf;
> +
> + if (size > 11) {
> + do {
> + if (!rt->flv_off) {
> + //skip flv header
> + if (buf_temp[0] == 'F' && buf_temp[1] == 'L' && buf_temp[2] == 'V') {
> + buf_temp += 9 + 4;
> + size_temp -= 9 + 4;
> + }
> +
> + pkttype = bytestream_get_byte(&buf_temp);
> + pktsize = bytestream_get_be24(&buf_temp);
> + ts = bytestream_get_be24(&buf_temp);
> + ts |= bytestream_get_byte(&buf_temp) << 24;
> + bytestream_get_be24(&buf_temp);
> + size_temp -= 11;
> + rt->flv_size = pktsize;
> +
> + //force 12bytes header
> + if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
> + pkttype == RTMP_PT_NOTIFY) {
> + if (pkttype == RTMP_PT_NOTIFY)
> + pktsize += 16;
> + rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
> + }
> +
> + //crutch: can be big packet (128k), better to send it right here.
//this can be a big packet, it's better to send it right here
> + ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL, pkttype, ts, pktsize);
> + rt->out_pkt.extra = rt->main_channel_id;
> + rt->flv_data = rt->out_pkt.data;
> +
> + if (pkttype == RTMP_PT_NOTIFY)
> + ff_amf_write_string(&rt->flv_data, "@setDataFrame");
> + }
> +
> + if (rt->flv_size - rt->flv_off > size_temp) {
> + bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
> + rt->flv_off += size_temp;
> + } else {
> + bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
> + rt->flv_off += rt->flv_size - rt->flv_off;
> + }
> +
> + if (rt->flv_off == rt->flv_size) {
> + bytestream_get_be32(&buf_temp);
> +
> + ff_rtmp_packet_write(rt->stream, &rt->out_pkt, rt->chunk_size, rt->prev_pkt[1]);
> + ff_rtmp_packet_destroy(&rt->out_pkt);
> + rt->flv_size = 0;
> + rt->flv_off = 0;
> + }
> + } while (buf_temp - buf < size_temp);
> + return size;
> + } else {
> + //close connection here
> + if (rt->out_pkt.data_size) {
> + ff_rtmp_packet_destroy(&rt->out_pkt);
> + rt->flv_size = 0;
> + rt->flv_off = 0;
> + }
> +
> + av_log(LOG_CONTEXT, AV_LOG_DEBUG, "UnPublishing stream...\n");
> + ff_rtmp_packet_create(&rt->out_pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 4096);
> + rt->flv_data = rt->out_pkt.data;
> + ff_amf_write_string(&rt->flv_data, "FCUnpublish");
> + ff_amf_write_number(&rt->flv_data, 5.0);
> + ff_amf_write_null(&rt->flv_data);
> + ff_amf_write_string(&rt->flv_data, rt->playpath);
> + rt->out_pkt.data_size = rt->flv_data - rt->out_pkt.data;
> +
> + ff_rtmp_packet_write(rt->stream, &rt->out_pkt, rt->chunk_size, rt->prev_pkt[1]);
> + ff_rtmp_packet_destroy(&rt->out_pkt);
> + return size;
> + }
> }
>
> URLProtocol rtmp_protocol = {
Ahem, why are doing this? There is rtmp_close() for final calls, and why
that if(size > 11) condition?
More information about the ffmpeg-devel
mailing list