On Sat, 11 Aug 2012, Martin Storsjö wrote:

On Thu, 9 Aug 2012, Jordi Ortiz wrote:

+        // generate packet header and put data into buffer for FLV demuxer
+        if (rt->flv_size - rt->flv_off < pkt->data_size + 15) {
+            rt->flv_data = cp =
+ av_realloc(rt->flv_data, rt->flv_off + pkt->data_size + 15);

If realloc fails, you will have overwritten the flv_data pointer, which then is leaked. You need to check the return value, and you need to keep the old pointer until you know the realloc succeeded.

+            rt->flv_size = rt->flv_off + pkt->data_size + 15;
+        } else {
+            cp = rt->flv_data;
+        }
+
+        bytestream2_init_writer(&pbc, cp + rt->flv_off,
+                                rt->flv_size - rt->flv_off);
+        bytestream2_put_byte(&pbc, pkt->type);
+        bytestream2_put_be24(&pbc, pkt->data_size);
+        bytestream2_put_be24(&pbc, ts);
+        bytestream2_put_byte(&pbc, ts >> 24);
+        bytestream2_put_be24(&pbc, 0);
+        bytestream2_put_buffer(&pbc, pkt->data, pkt->data_size);
+        bytestream2_put_be32(&pbc, 0);

Did you ever see the metadata that you received here? You don't update the flv_off to reflect the newly written data, so it's never actually returned. But this isn't everything you need to do in order to make that work. Please test and make sure that the metadata that the client sends actually gets handled properly by the flv demuxer.


Ok, so here's a number of problems. We've got data in rt->flv_data, and the variables rt->flv_size and rt->flv_off. In rtmp_read, we read data from rt->flv_off, up until rt->flv_size. So if we write more data into the buffer, we should write it at rt->flv_size and leave rt->flv_off untouched. If rt->flv_off == rt->flv_size, all data in the buffer has already been read, so instead of increasing flv_size, we could just set flv_off to 0 and flv_size to the size of the data we're going to write.

If you look at the handling of video/audio packets in get_packet, you'll see that it always sets flv_off to 0 - this code assumes that get_packet will never be called if there is unread data in the buffer.


The next problem is the startup in rtmp_open:

    do {
        ret = get_packet(s, 1);
    } while (ret == EAGAIN);
    if (ret < 0)
        goto fail;

    if (rt->is_input) {
        // generate FLV header for demuxer
        rt->flv_size = 13;
        rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
        rt->flv_off  = 0;
        memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);

The first loop,
    do {
        ret = get_packet(s, 1);
    } while (ret == EAGAIN);
is used for awaiting packets until the stream is set up and we can start receiving packets, the corresponding end criterion in get_packet is this:
        if (for_header && (rt->state == STATE_PLAYING || rt->state == 
STATE_PUBLISHING)) {
            ff_rtmp_packet_destroy(&rpkt);
            return 0;
        }

So the point is that we should set the right state while parsing the packets (in rtmp_parse_result), and if the setup was finished, we set the state playing/publishing, and then we return.

For your case, we should set a similar state once we received the publish invoke.

If we don't get the right state, we will write data into the flv_data buffer, and then return 0. Then we will overwrite all this data in the "generate FLV header for demuxer" section.


Then next, in handle_notify, you copy the full payload of the rtmp packet into the output metadata packet. This includes the @setDataFrame string, which makes the flv demuxer ignore the packet. So when you create this output metadata packet, you need to skip over the @setDataFrame part of the packet and just copy the rest of it. Then the flv demuxer will handle it properly.


So, things you need to do:
1) Set a corresponding state like playing/publishing once we got the publish invoke
2) Fix the way you produce data in handle_notify:
- Either you can just do like get_packet(), that is, set flv_off = 0, flv_size = the amount you'll write, flv_data = realloc(flv_data, flv_size) (+ error checking) - Bonus version, which OTOH isn't needed in the current way the code is written (pseudocode, lacking error checking and such):
 if (flv_off < flv_size) {
     old_flv_size = flv_size;
     flv_size += my_data_size;
 } else {
     old_flv_size = 0;
     flv_size = my_data_size;
 }
 flv_data = realloc(flv_data, flv_size);
 memcpy(flv_data + old_flv_size, my_data, my_data_size);

But since the rest of the code assumes that flv_off == flv_size, this is a bit unnecessary.
3) Skip copying the @setDataFrame part into the output packet


Then I think this should work more like it should. :-)

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

Reply via email to