Opened 4 years ago

Last modified 4 years ago

#3127 new defect

Video stream publishing via RTMPT

Reported by: goodvinj Owned by:
Priority: normal Component: avformat
Version: git-master Keywords:
Cc: Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

I have the latest FFMPEG built with librtmp support.
I'm trying to publish video stream to RED5 media server via RTMPT, but I see only few seconds of video (after that FFMPEG stops sending video).
When I use RTMP (not RTMPT) there is no such trouble.

On the other hand Flash Player publishes stream over RTMPT to RED5 without issues.

Also I've tried to build FFMPEG without librtmp support, but FFMPEG hangs on avio_open in this case.

Here is a log after avio_open call:

2013-11-12 20:05:50.031 [2824 ] DEBUG [http @ 01076140] request: POST /open/1 HTTP/1.1

Accept: */*
Connection: keep-alive
Host: localhost:5080
Content-Length: 1
Cache-Control: no-cache
Content-type: application/x-fcs
User-Agent: Shockwave Flash


2013-11-12 20:05:50.037 [2824 ] DEBUG [http @ 01076140] header='HTTP/1.1 200 OK'
2013-11-12 20:05:50.037 [2824 ] DEBUG [http @ 01076140] http_code=200
2013-11-12 20:05:50.037 [2824 ] DEBUG [http @ 01076140] header='Server: Apache-Coyote/1.1'
2013-11-12 20:05:50.038 [2824 ] DEBUG [http @ 01076140] header='Connection: Keep-Alive'
2013-11-12 20:05:50.038 [2824 ] DEBUG [http @ 01076140] header='Cache-Control: no-cache'
2013-11-12 20:05:50.038 [2824 ] DEBUG [http @ 01076140] header='Content-Type: application/x-fcs'
2013-11-12 20:05:50.039 [2824 ] DEBUG [http @ 01076140] header='Content-Length: 14'
2013-11-12 20:05:50.039 [2824 ] DEBUG [http @ 01076140] header='Date: Tue, 12 Nov 2013 13:05:50 GMT'
2013-11-12 20:05:50.040 [2824 ] DEBUG [http @ 01076140] header=

That's all - avio_open never returns.

I use the following command line for the test:

ffmpeg -re -i file.flv -acodec copy -vcodec h264 -f flv rtmpt://localhost:5080/oflaDemo/stream1384247072828

Attachments (2)

0001-Partial-fix-for-the-ticket-3127-Video-stream-publish.patch (820 bytes) - added by goodvinj 4 years ago.
Fix for the avio_open hangs
0001-Partial-fix-for-the-ticket-3127-second-try.patch (1.2 KB) - added by goodvinj 4 years ago.
Patch - second try

Download all attachments as: .zip

Change History (9)

comment:1 Changed 4 years ago by cehoyos

Is this a regression (did it work with older versions of FFmpeg)?

comment:2 Changed 4 years ago by goodvinj

I'd tried older versions, but they didn't work too.
Maybe at some point in the past it worked, I don't know.

comment:3 Changed 4 years ago by goodvinj

I've found the reason of hangs in "avio_open":

"rtmp_http_open" tries to read server reply with unique id and calls "ffurl_read".

It expects that "ffurl_read" returns AVERROR_EOF on completion, but "ffurl_read" returns 0.

It's because "ffurl_read" calls "retry_transfer_wrapper" which calls "http_read" (as transfer_func).
"http_read" returns AVERROR_EOF, but there is the code:

        } else if (ret < 1)
            return (ret < 0 && ret != AVERROR_EOF) ? ret : len;

so "retry_transfer_wrapper" returns len==0 instead of AVERROR_EOF, and "ffurl_read" returns 0.

Then "rtmp_http_open" calls "ffurl_read" and so on.

I'd fixed this by the following code in "rtmp_http_open":

    for (;;) {
        ret = ffurl_read(rt->stream, rt->client_id + off, sizeof(rt->client_id) - off);
        if (ret == 0 || ret == AVERROR_EOF)
            break;
        if (ret < 0)
            goto fail;
        off += ret;
        if (off == sizeof(rt->client_id)) {
            ret = AVERROR(EIO);
            goto fail;
        }
    }

Next issue occurs in "rtmp_handshake" (it hangs too).
On handshake "rtmp_http_read" is called, "rtmp_http_read" calls "ffurl_read" and expects AVERROR_EOF on completion. But "ffurl_read" returns 0 again, so we get an infinite loop there.
I'd changed "rtmp_http_read":

    do {
        ret = ffurl_read(rt->stream, buf + off, size);
        if (ret < 0 && ret != AVERROR_EOF)
            return ret;

        if (ret == 0 || ret == AVERROR_EOF) {
            if (rt->finishing) {

After these changes I'd reverted all my changes and changed only these lines in "retry_transfer_wrapper":

        } else if (ret < 1)
            return (ret < 0 && ret != AVERROR_EOF) ? ret : len;

to

        } else if (ret < 1)
            return (ret < 0) ? ret : len;

Now FFMPEG sends video over RTMPT (without librtmp support).

comment:4 Changed 4 years ago by goodvinj

  • Component changed from undetermined to avformat

comment:5 Changed 4 years ago by cehoyos

Please send your patch - made with git format-patch - to the ffmpeg-devel mailing list where it can be discussed.

comment:6 Changed 4 years ago by cehoyos

  • Priority changed from important to normal

Changed 4 years ago by goodvinj

Fix for the avio_open hangs

comment:7 Changed 4 years ago by goodvinj

I've found that "ffurl_read" can return 0 by the specification:

/**
 * Read up to size bytes from the resource accessed by h, and store
 * the read bytes in buf.
 *
 * @return The number of bytes actually read, or a negative value
 * corresponding to an AVERROR code in case of error. A value of zero
 * indicates that it is not possible to read more from the accessed
 * resource (except if the value of the size argument is also zero).
 */
int ffurl_read(URLContext *h, unsigned char *buf, int size);

So the right patch must check "ffurl_read" result on 0, and the old patch is invalid.

Changed 4 years ago by goodvinj

Patch - second try

Note: See TracTickets for help on using tickets.