On Tue, 31 Jul 2012, Jordi Ortiz wrote:

@@ -1072,11 +1341,145 @@ static int handle_invoke(URLContext *s, RTMPPacket 
*pkt)
    } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
        if ((ret = gen_check_bw(s, rt)) < 0)
            return ret;
+    } else if (!memcmp(pkt->data, "\002\000\015releaseStream", 16) ||
+               !memcmp(pkt->data, "\002\000\011FCPublish", 12)     ||
+               !memcmp(pkt->data, "\002\000\007publish", 10)       ||
+               !memcmp(pkt->data, "\002\000\010_checkbw", 11)      ||
+               !memcmp(pkt->data, "\002\000\014createStream", 15)) {
+        double seqnum;
+        char filename[64];
+        char command[64];
+        char statusmsg[128];
+        int stringlen;
+        char *pchar;
+        const uint8_t *p = pkt->data;
+        uint8_t *pp      = NULL;
+        RTMPPacket spkt  = { 0 };
+        GetByteContext gbc;
+
+        bytestream2_init(&gbc, p, pkt->data_size);
+        if (ff_amf_read_string(&gbc, command, sizeof(command),
+                               &stringlen)) {
+            av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
+            return AVERROR_BUG;
+        }
+
+        ret = ff_amf_read_number(&gbc, &seqnum);
+        if (ret)
+            return ret;
+        ret    = ff_amf_read_null(&gbc);
+        if (ret)
+            return ret;
+        if (!strcmp(command, "FCPublish") ||
+            !strcmp(command, "publish")) {
+            ret = ff_amf_read_string(&gbc, filename,
+                                     sizeof(filename), &stringlen);
+            // check with url
+            if (s->filename) {
+                pchar = strrchr(s->filename, '/');
+                pchar++;
+                if (strcmp(pchar, filename))
+                    av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
+                           " %s\n", filename, pchar);
+            }
+        }
+
+        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;
+        if (!strcmp(command, "FCPublish"))
+            ff_amf_write_string(&pp, "onFCPublish");
+        else if (!strcmp(command, "publish")) {
+            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), "LibAVFormat %d",
+                     LIBAVFORMAT_VERSION_INT);
+            ff_amf_write_string(&pp, statusmsg);
+            ff_amf_write_object_end(&pp);
+
+        } else {
+            ff_amf_write_string(&pp, "_result");
+            ff_amf_write_number(&pp, seqnum);
+            ff_amf_write_null(&pp);
+        }
+        spkt.data_size = pp - spkt.data;
+        if ((ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->chunk_size,
+                                        rt->prev_pkt[1])) < 0)
+            return ret;
+        ff_rtmp_packet_destroy(&spkt);
+    } else {
+        av_log(s, AV_LOG_WARNING,
+               "Unexpected command in PT_INVOKE\n");

This warning message also shows up in other cases than when listening, so it's unrelated to your patch.

FWIW, I tested your patch with WireCast, and it hangs at startup. You need to set spkt.extra = 1 on the NetStream.Publish.Start packet. (When crosschecking with wowza, wowza also sends a Stream Begin packet with the 32-bit value 1 as a reply to the publish() call, but that doesn't seem to be required for WireCast to proceed).

Still the connection fails after a short while. WireCast sends a Change Chunk Size packet between two chunks of data that belong to one single packet, and this is pretty hard to handle properly the way ff_rtmp_packet_read_internal is written right now.

FWIW, the whole RTMP code seems to be written assuming that there's one single chunk size for both sender and receiver, but that's not the case, the server and client have different individual chunk sizes. Ideally we should split this into two variables and handle it properly. (This is hacked around by signalling the same chunk size as the server set for its own connection, when publishing data, so that both directions use the same value.)

// Martin
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to