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