On Tue, Aug 14, 2012 at 10:08 PM, Martin Storsjö <mar...@martin.st> wrote:
> On Mon, 13 Aug 2012, Samuel Pitoiset wrote:
>
>> ---
>> doc/protocols.texi      |   3 ++
>> libavformat/rtmpproto.c | 127
>> ++++++++++++++++++++++++++++++++++++++++++++++++
>> libavformat/version.h   |   2 +-
>> 3 files changed, 131 insertions(+), 1 deletion(-)
>>
>> diff --git a/doc/protocols.texi b/doc/protocols.texi
>> index bdb3e8c..ea5706f 100644
>> --- a/doc/protocols.texi
>> +++ b/doc/protocols.texi
>> @@ -251,6 +251,9 @@ Size of the decompressed SWF file, required for
>> SWFVerification.
>> @item rtmp_swfurl
>> URL of the SWF player for the media. By default no value will be sent.
>>
>> +@item rtmp_swfverify
>> +URL to player swf file, compute hash/size automatically.
>> +
>> @item rtmp_tcurl
>> URL of the target stream. Defaults to proto://host[:port]/app.
>>
>> diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c
>> index 1afc35b..8a99eb4 100644
>> --- a/libavformat/rtmpproto.c
>> +++ b/libavformat/rtmpproto.c
>> @@ -41,6 +41,10 @@
>> #include "rtmppkt.h"
>> #include "url.h"
>>
>> +#if CONFIG_ZLIB
>> +#include <zlib.h>
>> +#endif
>> +
>> //#define DEBUG
>>
>> #define APP_MAX_LENGTH 128
>> @@ -94,6 +98,7 @@ typedef struct RTMPContext {
>>     int           swfhash_len;                ///< length of the SHA256
>> hash
>>     int           swfsize;                    ///< size of the
>> decompressed SWF file
>>     char*         swfurl;                     ///< url of the swf player
>> +    char*         swfverify;                  ///< URL to player swf
>> file, compute hash/size automatically
>>     char          swfverification[42];        ///< hash of the SWF
>> verification
>>     char*         pageurl;                    ///< url of the web page
>>     char*         subscribe;                  ///< name of live stream to
>> subscribe
>> @@ -799,6 +804,122 @@ static int rtmp_calc_swf_verification(URLContext *s,
>> RTMPContext *rt,
>>     return 0;
>> }
>>
>> +#if CONFIG_ZLIB
>> +static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
>> +                                     uint8_t **out_data, int64_t
>> *out_size)
>> +{
>> +    z_stream zs = { 0 };
>> +    void *ptr;
>> +    int size;
>> +    int ret = 0;
>> +
>> +    zs.avail_in = in_size;
>> +    zs.next_in  = in_data;
>> +    ret = inflateInit(&zs);
>> +    if (ret != Z_OK)
>> +        return ret;
>
>
> You can't mix and match error codes from different systems. In this case,
> you were lucky, and the zlib error codes actually are negative values, but
> they of course mean totally different things than the AVERROR ones, so it
> will end up meaning something totally different.

Indeed, I checked if the return values of inflate was negative.
Does it okay for you?

>
>
>> +
>> +    do {
>> +        uint8_t tmp_buf[16384];
>> +
>> +        zs.avail_out = sizeof(tmp_buf);
>> +        zs.next_out  = tmp_buf;
>> +
>> +        ret = inflate(&zs, Z_NO_FLUSH);
>> +        if (ret != Z_OK && ret != Z_STREAM_END)
>> +            goto fail;
>
>
> How will this behave if the decompressed data is exactly a multiple of 16k.
> On the last call that returns data, does this return Z_OK or Z_STREAM_END?
> Since zs.avail_out will be 0, we will run another round of the loop. What
> error message will it return at this point, will it return Z_STREAM_END
> again, or something else? If it returns something else, you will actually
> return an error from this function. Please test this and make sure it works
> properly.

It returns Z_STREAM_END in these cases.

>
>
>> +
>> +        size = sizeof(tmp_buf) - zs.avail_out;
>> +        if (!(ptr = av_realloc(*out_data, *out_size + size))) {
>> +            ret = AVERROR(ENOMEM);
>> +            goto fail;
>> +        }
>> +        *out_data = ptr;
>> +
>> +        memcpy(*out_data + *out_size, tmp_buf, size);
>> +        *out_size += size;
>
>
> This could be done without the memcpy, if you'd reallocate to add the same
> 16k extra space before inflating. But I guess that's not absolutely
> necessary for this to go in...

Ok.

>
>
>> +    } while (zs.avail_out == 0);
>> +
>> +fail:
>> +    inflateEnd(&zs);
>> +    return ret;
>> +}
>> +#endif
>> +
>> +static int rtmp_calc_swfhash(URLContext *s)
>> +{
>> +    RTMPContext *rt = s->priv_data;
>> +    uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
>> +    int64_t in_size, out_size;
>> +    URLContext *stream;
>> +    char swfhash[32];
>> +    int swfsize;
>> +    int ret = 0;
>> +
>> +    /* Get the SWF player file. */
>> +    if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
>> +                          &s->interrupt_callback, NULL)) < 0) {
>> +        av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n",
>> rt->swfverify);
>> +        goto fail;
>> +    }
>> +
>> +    if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
>> +        ret = AVERROR(EIO);
>> +        goto fail;
>> +    }
>
>
> If the url in question doesn't provide a size, we will fail. The alternative
> would be to read data in blocks until we reach EOF, reallocating the buffer
> along the way. Not sure it's necessary though...

Ok.

>
>
>> +
>> +    if (!(in_data = av_malloc(in_size))) {
>> +        ret = AVERROR(ENOMEM);
>> +        goto fail;
>> +    }
>> +
>> +    if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
>> +        goto fail;
>> +
>> +    if (!memcmp(in_data, "CWS", 3)) {
>
>
> What if in_size < 3?

We read out of bounds. I added a check here.

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



-- 
Best regards,
Samuel Pitoiset.
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to