diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-08-16 16:12:45 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-08-16 16:20:30 +0200 |
commit | c581cb4e4fd3f8387766d3606560b2900728883a (patch) | |
tree | ecaecc6d276510379d8e399e88937c10a778be85 /libavformat | |
parent | 208d6e6615e3c2e09de5aab92745e13da86aa827 (diff) | |
parent | 232e35de2e139cc2d34ed67a34dedbbc5da56052 (diff) | |
download | ffmpeg-c581cb4e4fd3f8387766d3606560b2900728883a.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master:
Fix even more missing includes after the common.h removal
build: Factor out rangecoder dependencies to CONFIG_RANGECODER
build: Factor out error resilience dependencies to CONFIG_ERROR_RESILIENCE
x86: avcodec: Consistently name all init files
Add more missing includes after removing the implicit common.h
Add some more missing includes after removing the implicit common.h
Don't include common.h from avutil.h
rtmp: Automatically compute the hash for SWFVerification
Conflicts:
configure
doc/APIchanges
doc/examples/decoding_encoding.c
libavcodec/Makefile
libavcodec/assdec.c
libavcodec/audio_frame_queue.c
libavcodec/avpacket.c
libavcodec/dv_profile.c
libavcodec/dwt.c
libavcodec/libtheoraenc.c
libavcodec/rawdec.c
libavcodec/rv40dsp.c
libavcodec/tiff.c
libavcodec/tiffenc.c
libavcodec/v210dec.h
libavcodec/vc1dsp.c
libavcodec/x86/Makefile
libavfilter/asrc_anullsrc.c
libavfilter/avfilter.c
libavfilter/buffer.c
libavfilter/formats.c
libavfilter/vf_ass.c
libavfilter/vf_drawtext.c
libavfilter/vf_fade.c
libavfilter/vf_select.c
libavfilter/video.c
libavfilter/vsrc_testsrc.c
libavformat/version.h
libavutil/audioconvert.c
libavutil/error.h
libavutil/version.h
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/network.c | 1 | ||||
-rw-r--r-- | libavformat/rtmpproto.c | 134 | ||||
-rw-r--r-- | libavformat/version.h | 2 |
3 files changed, 136 insertions, 1 deletions
diff --git a/libavformat/network.c b/libavformat/network.c index 6b4cb570b3..0e79cae7bf 100644 --- a/libavformat/network.c +++ b/libavformat/network.c @@ -21,6 +21,7 @@ #include "libavutil/avutil.h" #include "network.h" #include "libavcodec/internal.h" +#include "libavutil/mem.h" #define THREADS (HAVE_PTHREADS || (defined(WIN32) && !defined(__MINGW32CE__))) diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index e3bcf3d843..9520b409e8 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 @@ -95,6 +99,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 @@ -825,6 +830,129 @@ 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 AVERROR_UNKNOWN; + + 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) { + ret = AVERROR_UNKNOWN; + goto fail; + } + + 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; + } 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 (!(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 (in_size < 3) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + if (!memcmp(in_data, "CWS", 3)) { + /* Decompress the SWF player file using Zlib. */ + if (!(out_data = av_malloc(8))) { + ret = AVERROR(ENOMEM); + goto fail; + } + *in_data = 'F'; // magic stuff + memcpy(out_data, in_data, 8); + out_size = 8; + +#if CONFIG_ZLIB + if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8, + &out_data, &out_size)) < 0) + goto fail; +#else + av_log(s, AV_LOG_ERROR, + "Zlib is required for decompressing the SWF player file.\n"); + ret = AVERROR(EINVAL); + goto fail; +#endif + swfsize = out_size; + swfdata = out_data; + } else { + swfsize = in_size; + swfdata = in_data; + } + + /* Compute the SHA256 hash of the SWF player file. */ + if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0, + "Genuine Adobe Flash Player 001", 30, + swfhash)) < 0) + goto fail; + + /* Set SWFVerification parameters. */ + av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0); + rt->swfsize = swfsize; + +fail: + av_freep(&in_data); + av_freep(&out_data); + ffurl_close(stream); + return ret; +} + /** * Perform handshake with the server by means of exchanging pseudorandom data * signed with HMAC-SHA2 digest. @@ -1492,6 +1620,11 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) goto fail; } + if (rt->swfverify) { + if ((ret = rtmp_calc_swfhash(s)) < 0) + goto fail; + } + rt->state = STATE_START; if ((ret = rtmp_handshake(s, rt)) < 0) goto fail; @@ -1784,6 +1917,7 @@ static const AVOption rtmp_options[] = { {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC}, {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {0}, 0, INT_MAX, DEC}, {"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, + {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC}, {"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, { NULL }, }; diff --git a/libavformat/version.h b/libavformat/version.h index d89b346c1d..3703903eb2 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 54 #define LIBAVFORMAT_VERSION_MINOR 24 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ |