* qatar/master: (29 commits) doc: update libavfilter documentation tls: Use the URLContext as logging context aes: Avoid illegal read and don't generate more key than we use. mpc7: Fix memset call in mpc7_decode_frame function atrac1: use correct context for av_log() apedec: consume the whole packet when copying to the decoder buffer. apedec: do not needlessly copy s->samples to nblocks. apedec: check output buffer size after calculating actual output size apedec: remove unneeded entropy decoder normalization. truespeech: use memmove() in truespeech_update_filters() vorbisdec: remove AVCODEC_MAX_AUDIO_FRAME_SIZE check vorbisdec: remove unneeded buf_size==0 check vorbisdec: return proper error codes instead of made-up ones http: Don't add a Range: bytes=0- header for POST sunrast: Check for invalid/corrupted bitstream http: Change the chunksize AVOption into chunked_post http: Add encoding/decoding flags to the AVOptions avconv: remove some codec-specific hacks crypto: add decoding flag to options. tls: use AVIO_FLAG_NONBLOCK instead of deprecated URL_FLAG_NONBLOCK ... Conflicts: doc/libavfilter.texi libavcodec/atrac1.c libavcodec/sunrast.c Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n0.9
@@ -2122,10 +2122,6 @@ static int transcode_init(OutputFile *output_files, | |||||
codec->frame_size = icodec->frame_size; | codec->frame_size = icodec->frame_size; | ||||
codec->audio_service_type = icodec->audio_service_type; | codec->audio_service_type = icodec->audio_service_type; | ||||
codec->block_align= icodec->block_align; | codec->block_align= icodec->block_align; | ||||
if(codec->block_align == 1 && codec->codec_id == CODEC_ID_MP3) | |||||
codec->block_align= 0; | |||||
if(codec->codec_id == CODEC_ID_AC3) | |||||
codec->block_align= 0; | |||||
break; | break; | ||||
case AVMEDIA_TYPE_VIDEO: | case AVMEDIA_TYPE_VIDEO: | ||||
codec->pix_fmt = icodec->pix_fmt; | codec->pix_fmt = icodec->pix_fmt; | ||||
@@ -36,11 +36,10 @@ and the vflip filter before merging it back with the other stream by | |||||
overlaying it on top. You can use the following command to achieve this: | overlaying it on top. You can use the following command to achieve this: | ||||
@example | @example | ||||
./ffmpeg -i in.avi -s 240x320 -vf "[in] split [T1], fifo, [T2] overlay= 0:240 [out]; [T1] fifo, crop=0:0:-1:240, vflip [T2] | |||||
./ffmpeg -i input -vf "[in] split [T1], fifo, [T2] overlay=0:H/2 [out]; [T1] fifo, crop=iw:ih/2:0:ih/2, vflip [T2]" output | |||||
@end example | @end example | ||||
where input_video.avi has a vertical resolution of 480 pixels. The | |||||
result will be that in output the top half of the video is mirrored | |||||
The result will be that in output the top half of the video is mirrored | |||||
onto the bottom half. | onto the bottom half. | ||||
Video filters are loaded using the @var{-vf} option passed to | Video filters are loaded using the @var{-vf} option passed to | ||||
@@ -2165,10 +2165,6 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, | |||||
codec->frame_size = icodec->frame_size; | codec->frame_size = icodec->frame_size; | ||||
codec->audio_service_type = icodec->audio_service_type; | codec->audio_service_type = icodec->audio_service_type; | ||||
codec->block_align= icodec->block_align; | codec->block_align= icodec->block_align; | ||||
if(codec->block_align == 1 && codec->codec_id == CODEC_ID_MP3) | |||||
codec->block_align= 0; | |||||
if(codec->codec_id == CODEC_ID_AC3) | |||||
codec->block_align= 0; | |||||
break; | break; | ||||
case AVMEDIA_TYPE_VIDEO: | case AVMEDIA_TYPE_VIDEO: | ||||
codec->pix_fmt = icodec->pix_fmt; | codec->pix_fmt = icodec->pix_fmt; | ||||
@@ -140,8 +140,6 @@ typedef struct APEContext { | |||||
uint32_t CRC; ///< frame CRC | uint32_t CRC; ///< frame CRC | ||||
int frameflags; ///< frame flags | int frameflags; ///< frame flags | ||||
int currentframeblocks; ///< samples (per channel) in current frame | |||||
int blocksdecoded; ///< count of decoded samples in current frame | |||||
APEPredictor predictor; ///< predictor used for final reconstruction | APEPredictor predictor; ///< predictor used for final reconstruction | ||||
int32_t decoded0[BLOCKS_PER_LOOP]; ///< decoded data for the first channel | int32_t decoded0[BLOCKS_PER_LOOP]; ///< decoded data for the first channel | ||||
@@ -157,7 +155,6 @@ typedef struct APEContext { | |||||
uint8_t *data; ///< current frame data | uint8_t *data; ///< current frame data | ||||
uint8_t *data_end; ///< frame data end | uint8_t *data_end; ///< frame data end | ||||
const uint8_t *ptr; ///< current position in frame data | const uint8_t *ptr; ///< current position in frame data | ||||
const uint8_t *last_ptr; ///< position where last 4608-sample block ended | |||||
int error; | int error; | ||||
} APEContext; | } APEContext; | ||||
@@ -457,8 +454,6 @@ static void entropy_decode(APEContext *ctx, int blockstodecode, int stereo) | |||||
int32_t *decoded0 = ctx->decoded0; | int32_t *decoded0 = ctx->decoded0; | ||||
int32_t *decoded1 = ctx->decoded1; | int32_t *decoded1 = ctx->decoded1; | ||||
ctx->blocksdecoded = blockstodecode; | |||||
if (ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE) { | if (ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE) { | ||||
/* We are pure silence, just memset the output buffer. */ | /* We are pure silence, just memset the output buffer. */ | ||||
memset(decoded0, 0, blockstodecode * sizeof(int32_t)); | memset(decoded0, 0, blockstodecode * sizeof(int32_t)); | ||||
@@ -470,9 +465,6 @@ static void entropy_decode(APEContext *ctx, int blockstodecode, int stereo) | |||||
*decoded1++ = ape_decode_value(ctx, &ctx->riceX); | *decoded1++ = ape_decode_value(ctx, &ctx->riceX); | ||||
} | } | ||||
} | } | ||||
if (ctx->blocksdecoded == ctx->currentframeblocks) | |||||
range_dec_normalize(ctx); /* normalize to use up all bytes */ | |||||
} | } | ||||
static int init_entropy_decoder(APEContext *ctx) | static int init_entropy_decoder(APEContext *ctx) | ||||
@@ -492,9 +484,6 @@ static int init_entropy_decoder(APEContext *ctx) | |||||
ctx->frameflags = bytestream_get_be32(&ctx->ptr); | ctx->frameflags = bytestream_get_be32(&ctx->ptr); | ||||
} | } | ||||
/* Keep a count of the blocks decoded in this frame */ | |||||
ctx->blocksdecoded = 0; | |||||
/* Initialize the rice structs */ | /* Initialize the rice structs */ | ||||
ctx->riceX.k = 10; | ctx->riceX.k = 10; | ||||
ctx->riceX.ksum = (1 << ctx->riceX.k) * 16; | ctx->riceX.ksum = (1 << ctx->riceX.k) * 16; | ||||
@@ -824,25 +813,22 @@ static int ape_decode_frame(AVCodecContext *avctx, | |||||
int buf_size = avpkt->size; | int buf_size = avpkt->size; | ||||
APEContext *s = avctx->priv_data; | APEContext *s = avctx->priv_data; | ||||
int16_t *samples = data; | int16_t *samples = data; | ||||
uint32_t nblocks; | |||||
int i; | int i; | ||||
int blockstodecode; | |||||
int bytes_used; | |||||
/* should not happen but who knows */ | |||||
if (BLOCKS_PER_LOOP * 2 * avctx->channels > *data_size) { | |||||
av_log (avctx, AV_LOG_ERROR, "Output buffer is too small.\n"); | |||||
return AVERROR(EINVAL); | |||||
} | |||||
int blockstodecode, out_size; | |||||
int bytes_used = 0; | |||||
/* this should never be negative, but bad things will happen if it is, so | /* this should never be negative, but bad things will happen if it is, so | ||||
check it just to make sure. */ | check it just to make sure. */ | ||||
av_assert0(s->samples >= 0); | av_assert0(s->samples >= 0); | ||||
if(!s->samples){ | if(!s->samples){ | ||||
uint32_t offset; | |||||
uint32_t nblocks, offset; | |||||
void *tmp_data; | void *tmp_data; | ||||
if (!buf_size) { | |||||
*data_size = 0; | |||||
return 0; | |||||
} | |||||
if (buf_size < 8) { | if (buf_size < 8) { | ||||
av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); | av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); | ||||
return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
@@ -853,7 +839,7 @@ static int ape_decode_frame(AVCodecContext *avctx, | |||||
return AVERROR(ENOMEM); | return AVERROR(ENOMEM); | ||||
s->data = tmp_data; | s->data = tmp_data; | ||||
s->dsp.bswap_buf((uint32_t*)s->data, (const uint32_t*)buf, buf_size >> 2); | s->dsp.bswap_buf((uint32_t*)s->data, (const uint32_t*)buf, buf_size >> 2); | ||||
s->ptr = s->last_ptr = s->data; | |||||
s->ptr = s->data; | |||||
s->data_end = s->data + buf_size; | s->data_end = s->data + buf_size; | ||||
nblocks = bytestream_get_be32(&s->ptr); | nblocks = bytestream_get_be32(&s->ptr); | ||||
@@ -873,7 +859,7 @@ static int ape_decode_frame(AVCodecContext *avctx, | |||||
av_log(avctx, AV_LOG_ERROR, "Invalid sample count: %u.\n", nblocks); | av_log(avctx, AV_LOG_ERROR, "Invalid sample count: %u.\n", nblocks); | ||||
return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
} | } | ||||
s->currentframeblocks = s->samples = nblocks; | |||||
s->samples = nblocks; | |||||
memset(s->decoded0, 0, sizeof(s->decoded0)); | memset(s->decoded0, 0, sizeof(s->decoded0)); | ||||
memset(s->decoded1, 0, sizeof(s->decoded1)); | memset(s->decoded1, 0, sizeof(s->decoded1)); | ||||
@@ -883,6 +869,8 @@ static int ape_decode_frame(AVCodecContext *avctx, | |||||
av_log(avctx, AV_LOG_ERROR, "Error reading frame header\n"); | av_log(avctx, AV_LOG_ERROR, "Error reading frame header\n"); | ||||
return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
} | } | ||||
bytes_used = buf_size; | |||||
} | } | ||||
if (!s->data) { | if (!s->data) { | ||||
@@ -890,8 +878,14 @@ static int ape_decode_frame(AVCodecContext *avctx, | |||||
return buf_size; | return buf_size; | ||||
} | } | ||||
nblocks = s->samples; | |||||
blockstodecode = FFMIN(BLOCKS_PER_LOOP, nblocks); | |||||
blockstodecode = FFMIN(BLOCKS_PER_LOOP, s->samples); | |||||
out_size = blockstodecode * avctx->channels * | |||||
av_get_bytes_per_sample(avctx->sample_fmt); | |||||
if (*data_size < out_size) { | |||||
av_log(avctx, AV_LOG_ERROR, "Output buffer is too small.\n"); | |||||
return AVERROR(EINVAL); | |||||
} | |||||
s->error=0; | s->error=0; | ||||
@@ -915,9 +909,7 @@ static int ape_decode_frame(AVCodecContext *avctx, | |||||
s->samples -= blockstodecode; | s->samples -= blockstodecode; | ||||
*data_size = blockstodecode * 2 * s->channels; | |||||
bytes_used = s->samples ? s->ptr - s->last_ptr : buf_size; | |||||
s->last_ptr = s->ptr; | |||||
*data_size = out_size; | |||||
return bytes_used; | return bytes_used; | ||||
} | } | ||||
@@ -935,7 +927,7 @@ AVCodec ff_ape_decoder = { | |||||
.init = ape_decode_init, | .init = ape_decode_init, | ||||
.close = ape_decode_close, | .close = ape_decode_close, | ||||
.decode = ape_decode_frame, | .decode = ape_decode_frame, | ||||
.capabilities = CODEC_CAP_SUBFRAMES, | |||||
.capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DELAY, | |||||
.flush = ape_flush, | .flush = ape_flush, | ||||
.long_name = NULL_IF_CONFIG_SMALL("Monkey's Audio"), | .long_name = NULL_IF_CONFIG_SMALL("Monkey's Audio"), | ||||
}; | }; |
@@ -284,7 +284,7 @@ static int atrac1_decode_frame(AVCodecContext *avctx, void *data, | |||||
if (buf_size < 212 * q->channels) { | if (buf_size < 212 * q->channels) { | ||||
av_log(avctx,AV_LOG_ERROR,"Not enough data to decode!\n"); | |||||
av_log(avctx, AV_LOG_ERROR, "Not enough data to decode!\n"); | |||||
return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
} | } | ||||
@@ -200,7 +200,7 @@ static int mpc7_decode_frame(AVCodecContext * avctx, | |||||
int off, out_size; | int off, out_size; | ||||
int bits_used, bits_avail; | int bits_used, bits_avail; | ||||
memset(bands, 0, sizeof(bands)); | |||||
memset(bands, 0, sizeof(*bands) * (c->maxbands + 1)); | |||||
if(buf_size <= 4){ | if(buf_size <= 4){ | ||||
av_log(avctx, AV_LOG_ERROR, "Too small buffer passed (%i bytes)\n", buf_size); | av_log(avctx, AV_LOG_ERROR, "Too small buffer passed (%i bytes)\n", buf_size); | ||||
return AVERROR(EINVAL); | return AVERROR(EINVAL); | ||||
@@ -68,7 +68,7 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data, | |||||
type = AV_RB32(buf+20); | type = AV_RB32(buf+20); | ||||
maptype = AV_RB32(buf+24); | maptype = AV_RB32(buf+24); | ||||
maplength = AV_RB32(buf+28); | maplength = AV_RB32(buf+28); | ||||
buf += 32; | |||||
buf += 32; | |||||
if (type < RT_OLD || type > RT_FORMAT_IFF) { | if (type < RT_OLD || type > RT_FORMAT_IFF) { | ||||
av_log(avctx, AV_LOG_ERROR, "invalid (compression) type\n"); | av_log(avctx, AV_LOG_ERROR, "invalid (compression) type\n"); | ||||
@@ -233,8 +233,7 @@ static void truespeech_update_filters(TSContext *dec, int16_t *out, int quart) | |||||
{ | { | ||||
int i; | int i; | ||||
for(i = 0; i < 86; i++) | |||||
dec->filtbuf[i] = dec->filtbuf[i + 60]; | |||||
memmove(dec->filtbuf, &dec->filtbuf[60], 86 * sizeof(*dec->filtbuf)); | |||||
for(i = 0; i < 60; i++){ | for(i = 0; i < 60; i++){ | ||||
dec->filtbuf[i + 86] = out[i] + dec->newvec[i] - (dec->newvec[i] >> 3); | dec->filtbuf[i + 86] = out[i] + dec->newvec[i] - (dec->newvec[i] >> 3); | ||||
out[i] += dec->newvec[i]; | out[i] += dec->newvec[i]; | ||||
@@ -168,7 +168,7 @@ static const char idx_err_str[] = "Index value %d out of range (0 - %d) for %s a | |||||
av_log(vc->avccontext, AV_LOG_ERROR,\ | av_log(vc->avccontext, AV_LOG_ERROR,\ | ||||
idx_err_str,\ | idx_err_str,\ | ||||
(int)(idx), (int)(limit - 1), #idx, __FILE__, __LINE__);\ | (int)(idx), (int)(limit - 1), #idx, __FILE__, __LINE__);\ | ||||
return -1;\ | |||||
return AVERROR_INVALIDDATA;\ | |||||
} | } | ||||
#define GET_VALIDATED_INDEX(idx, bits, limit) \ | #define GET_VALIDATED_INDEX(idx, bits, limit) \ | ||||
{\ | {\ | ||||
@@ -241,6 +241,7 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) | |||||
uint32_t *tmp_vlc_codes; | uint32_t *tmp_vlc_codes; | ||||
GetBitContext *gb = &vc->gb; | GetBitContext *gb = &vc->gb; | ||||
uint16_t *codebook_multiplicands; | uint16_t *codebook_multiplicands; | ||||
int ret = 0; | |||||
vc->codebook_count = get_bits(gb, 8) + 1; | vc->codebook_count = get_bits(gb, 8) + 1; | ||||
@@ -260,6 +261,7 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) | |||||
if (get_bits(gb, 24) != 0x564342) { | if (get_bits(gb, 24) != 0x564342) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, | av_log(vc->avccontext, AV_LOG_ERROR, | ||||
" %u. Codebook setup data corrupt.\n", cb); | " %u. Codebook setup data corrupt.\n", cb); | ||||
ret = AVERROR_INVALIDDATA; | |||||
goto error; | goto error; | ||||
} | } | ||||
@@ -268,6 +270,7 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) | |||||
av_log(vc->avccontext, AV_LOG_ERROR, | av_log(vc->avccontext, AV_LOG_ERROR, | ||||
" %u. Codebook's dimension is invalid (%d).\n", | " %u. Codebook's dimension is invalid (%d).\n", | ||||
cb, codebook_setup->dimensions); | cb, codebook_setup->dimensions); | ||||
ret = AVERROR_INVALIDDATA; | |||||
goto error; | goto error; | ||||
} | } | ||||
entries = get_bits(gb, 24); | entries = get_bits(gb, 24); | ||||
@@ -275,6 +278,7 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) | |||||
av_log(vc->avccontext, AV_LOG_ERROR, | av_log(vc->avccontext, AV_LOG_ERROR, | ||||
" %u. Codebook has too many entries (%u).\n", | " %u. Codebook has too many entries (%u).\n", | ||||
cb, entries); | cb, entries); | ||||
ret = AVERROR_INVALIDDATA; | |||||
goto error; | goto error; | ||||
} | } | ||||
@@ -332,6 +336,7 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) | |||||
} | } | ||||
if (current_entry>used_entries) { | if (current_entry>used_entries) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, " More codelengths than codes in codebook. \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " More codelengths than codes in codebook. \n"); | ||||
ret = AVERROR_INVALIDDATA; | |||||
goto error; | goto error; | ||||
} | } | ||||
} | } | ||||
@@ -399,17 +404,20 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) | |||||
} | } | ||||
if (j != used_entries) { | if (j != used_entries) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, "Bug in codevector vector building code. \n"); | av_log(vc->avccontext, AV_LOG_ERROR, "Bug in codevector vector building code. \n"); | ||||
ret = AVERROR_INVALIDDATA; | |||||
goto error; | goto error; | ||||
} | } | ||||
entries = used_entries; | entries = used_entries; | ||||
} else if (codebook_setup->lookup_type >= 2) { | } else if (codebook_setup->lookup_type >= 2) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, "Codebook lookup type not supported. \n"); | av_log(vc->avccontext, AV_LOG_ERROR, "Codebook lookup type not supported. \n"); | ||||
ret = AVERROR_INVALIDDATA; | |||||
goto error; | goto error; | ||||
} | } | ||||
// Initialize VLC table | // Initialize VLC table | ||||
if (ff_vorbis_len2vlc(tmp_vlc_bits, tmp_vlc_codes, entries)) { | if (ff_vorbis_len2vlc(tmp_vlc_bits, tmp_vlc_codes, entries)) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, " Invalid code lengths while generating vlcs. \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " Invalid code lengths while generating vlcs. \n"); | ||||
ret = AVERROR_INVALIDDATA; | |||||
goto error; | goto error; | ||||
} | } | ||||
codebook_setup->maxdepth = 0; | codebook_setup->maxdepth = 0; | ||||
@@ -424,7 +432,11 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) | |||||
codebook_setup->maxdepth = (codebook_setup->maxdepth+codebook_setup->nb_bits - 1) / codebook_setup->nb_bits; | codebook_setup->maxdepth = (codebook_setup->maxdepth+codebook_setup->nb_bits - 1) / codebook_setup->nb_bits; | ||||
if (init_vlc(&codebook_setup->vlc, codebook_setup->nb_bits, entries, tmp_vlc_bits, sizeof(*tmp_vlc_bits), sizeof(*tmp_vlc_bits), tmp_vlc_codes, sizeof(*tmp_vlc_codes), sizeof(*tmp_vlc_codes), INIT_VLC_LE)) { | |||||
if ((ret = init_vlc(&codebook_setup->vlc, codebook_setup->nb_bits, | |||||
entries, tmp_vlc_bits, sizeof(*tmp_vlc_bits), | |||||
sizeof(*tmp_vlc_bits), tmp_vlc_codes, | |||||
sizeof(*tmp_vlc_codes), sizeof(*tmp_vlc_codes), | |||||
INIT_VLC_LE))) { | |||||
av_log(vc->avccontext, AV_LOG_ERROR, " Error generating vlc tables. \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " Error generating vlc tables. \n"); | ||||
goto error; | goto error; | ||||
} | } | ||||
@@ -440,7 +452,7 @@ error: | |||||
av_free(tmp_vlc_bits); | av_free(tmp_vlc_bits); | ||||
av_free(tmp_vlc_codes); | av_free(tmp_vlc_codes); | ||||
av_free(codebook_multiplicands); | av_free(codebook_multiplicands); | ||||
return -1; | |||||
return ret; | |||||
} | } | ||||
// Process time domain transforms part (unused in Vorbis I) | // Process time domain transforms part (unused in Vorbis I) | ||||
@@ -458,7 +470,7 @@ static int vorbis_parse_setup_hdr_tdtransforms(vorbis_context *vc) | |||||
if (vorbis_tdtransform) { | if (vorbis_tdtransform) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, "Vorbis time domain transform data nonzero. \n"); | av_log(vc->avccontext, AV_LOG_ERROR, "Vorbis time domain transform data nonzero. \n"); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
} | } | ||||
return 0; | return 0; | ||||
@@ -550,7 +562,7 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) | |||||
av_log(vc->avccontext, AV_LOG_ERROR, | av_log(vc->avccontext, AV_LOG_ERROR, | ||||
"Floor value is too large for blocksize: %u (%"PRIu32")\n", | "Floor value is too large for blocksize: %u (%"PRIu32")\n", | ||||
rangemax, vc->blocksize[1] / 2); | rangemax, vc->blocksize[1] / 2); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
floor_setup->data.t1.list[0].x = 0; | floor_setup->data.t1.list[0].x = 0; | ||||
floor_setup->data.t1.list[1].x = rangemax; | floor_setup->data.t1.list[1].x = rangemax; | ||||
@@ -580,7 +592,7 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) | |||||
if (floor_setup->data.t0.amplitude_bits == 0) { | if (floor_setup->data.t0.amplitude_bits == 0) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, | av_log(vc->avccontext, AV_LOG_ERROR, | ||||
"Floor 0 amplitude bits is 0.\n"); | "Floor 0 amplitude bits is 0.\n"); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
floor_setup->data.t0.amplitude_offset = get_bits(gb, 8); | floor_setup->data.t0.amplitude_offset = get_bits(gb, 8); | ||||
floor_setup->data.t0.num_books = get_bits(gb, 4) + 1; | floor_setup->data.t0.num_books = get_bits(gb, 4) + 1; | ||||
@@ -589,7 +601,7 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) | |||||
floor_setup->data.t0.book_list = | floor_setup->data.t0.book_list = | ||||
av_malloc(floor_setup->data.t0.num_books); | av_malloc(floor_setup->data.t0.num_books); | ||||
if (!floor_setup->data.t0.book_list) | if (!floor_setup->data.t0.book_list) | ||||
return -1; | |||||
return AVERROR(ENOMEM); | |||||
/* read book indexes */ | /* read book indexes */ | ||||
{ | { | ||||
int idx; | int idx; | ||||
@@ -610,7 +622,7 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) | |||||
av_malloc((floor_setup->data.t0.order + 1 + max_codebook_dim) | av_malloc((floor_setup->data.t0.order + 1 + max_codebook_dim) | ||||
* sizeof(*floor_setup->data.t0.lsp)); | * sizeof(*floor_setup->data.t0.lsp)); | ||||
if (!floor_setup->data.t0.lsp) | if (!floor_setup->data.t0.lsp) | ||||
return -1; | |||||
return AVERROR(ENOMEM); | |||||
/* debug output parsed headers */ | /* debug output parsed headers */ | ||||
av_dlog(NULL, "floor0 order: %u\n", floor_setup->data.t0.order); | av_dlog(NULL, "floor0 order: %u\n", floor_setup->data.t0.order); | ||||
@@ -634,7 +646,7 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) | |||||
} | } | ||||
} else { | } else { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, "Invalid floor type!\n"); | av_log(vc->avccontext, AV_LOG_ERROR, "Invalid floor type!\n"); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
} | } | ||||
return 0; | return 0; | ||||
@@ -672,7 +684,7 @@ static int vorbis_parse_setup_hdr_residues(vorbis_context *vc) | |||||
"partition out of bounds: type, begin, end, size, blocksize: %"PRIu16", %"PRIu32", %"PRIu32", %u, %"PRIu32"\n", | "partition out of bounds: type, begin, end, size, blocksize: %"PRIu16", %"PRIu32", %"PRIu32", %u, %"PRIu32"\n", | ||||
res_setup->type, res_setup->begin, res_setup->end, | res_setup->type, res_setup->begin, res_setup->end, | ||||
res_setup->partition_size, vc->blocksize[1] / 2); | res_setup->partition_size, vc->blocksize[1] / 2); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
res_setup->classifications = get_bits(gb, 6) + 1; | res_setup->classifications = get_bits(gb, 6) + 1; | ||||
@@ -737,7 +749,7 @@ static int vorbis_parse_setup_hdr_mappings(vorbis_context *vc) | |||||
if (get_bits(gb, 16)) { | if (get_bits(gb, 16)) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, "Other mappings than type 0 are not compliant with the Vorbis I specification. \n"); | av_log(vc->avccontext, AV_LOG_ERROR, "Other mappings than type 0 are not compliant with the Vorbis I specification. \n"); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
if (get_bits1(gb)) { | if (get_bits1(gb)) { | ||||
mapping_setup->submaps = get_bits(gb, 4) + 1; | mapping_setup->submaps = get_bits(gb, 4) + 1; | ||||
@@ -764,7 +776,7 @@ static int vorbis_parse_setup_hdr_mappings(vorbis_context *vc) | |||||
if (get_bits(gb, 2)) { | if (get_bits(gb, 2)) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, "%u. mapping setup data invalid.\n", i); | av_log(vc->avccontext, AV_LOG_ERROR, "%u. mapping setup data invalid.\n", i); | ||||
return -1; // following spec. | |||||
return AVERROR_INVALIDDATA; // following spec. | |||||
} | } | ||||
if (mapping_setup->submaps>1) { | if (mapping_setup->submaps>1) { | ||||
@@ -851,41 +863,42 @@ static int vorbis_parse_setup_hdr_modes(vorbis_context *vc) | |||||
static int vorbis_parse_setup_hdr(vorbis_context *vc) | static int vorbis_parse_setup_hdr(vorbis_context *vc) | ||||
{ | { | ||||
GetBitContext *gb = &vc->gb; | GetBitContext *gb = &vc->gb; | ||||
int ret; | |||||
if ((get_bits(gb, 8) != 'v') || (get_bits(gb, 8) != 'o') || | if ((get_bits(gb, 8) != 'v') || (get_bits(gb, 8) != 'o') || | ||||
(get_bits(gb, 8) != 'r') || (get_bits(gb, 8) != 'b') || | (get_bits(gb, 8) != 'r') || (get_bits(gb, 8) != 'b') || | ||||
(get_bits(gb, 8) != 'i') || (get_bits(gb, 8) != 's')) { | (get_bits(gb, 8) != 'i') || (get_bits(gb, 8) != 's')) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (no vorbis signature). \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (no vorbis signature). \n"); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
if (vorbis_parse_setup_hdr_codebooks(vc)) { | |||||
if ((ret = vorbis_parse_setup_hdr_codebooks(vc))) { | |||||
av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (codebooks). \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (codebooks). \n"); | ||||
return -2; | |||||
return ret; | |||||
} | } | ||||
if (vorbis_parse_setup_hdr_tdtransforms(vc)) { | |||||
if ((ret = vorbis_parse_setup_hdr_tdtransforms(vc))) { | |||||
av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (time domain transforms). \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (time domain transforms). \n"); | ||||
return -3; | |||||
return ret; | |||||
} | } | ||||
if (vorbis_parse_setup_hdr_floors(vc)) { | |||||
if ((ret = vorbis_parse_setup_hdr_floors(vc))) { | |||||
av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (floors). \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (floors). \n"); | ||||
return -4; | |||||
return ret; | |||||
} | } | ||||
if (vorbis_parse_setup_hdr_residues(vc)) { | |||||
if ((ret = vorbis_parse_setup_hdr_residues(vc))) { | |||||
av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (residues). \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (residues). \n"); | ||||
return -5; | |||||
return ret; | |||||
} | } | ||||
if (vorbis_parse_setup_hdr_mappings(vc)) { | |||||
if ((ret = vorbis_parse_setup_hdr_mappings(vc))) { | |||||
av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (mappings). \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (mappings). \n"); | ||||
return -6; | |||||
return ret; | |||||
} | } | ||||
if (vorbis_parse_setup_hdr_modes(vc)) { | |||||
if ((ret = vorbis_parse_setup_hdr_modes(vc))) { | |||||
av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (modes). \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (modes). \n"); | ||||
return -7; | |||||
return ret; | |||||
} | } | ||||
if (!get_bits1(gb)) { | if (!get_bits1(gb)) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (framing flag). \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis setup header packet corrupt (framing flag). \n"); | ||||
return -8; // framing flag bit unset error | |||||
return AVERROR_INVALIDDATA; // framing flag bit unset error | |||||
} | } | ||||
return 0; | return 0; | ||||
@@ -902,19 +915,19 @@ static int vorbis_parse_id_hdr(vorbis_context *vc) | |||||
(get_bits(gb, 8) != 'r') || (get_bits(gb, 8) != 'b') || | (get_bits(gb, 8) != 'r') || (get_bits(gb, 8) != 'b') || | ||||
(get_bits(gb, 8) != 'i') || (get_bits(gb, 8) != 's')) { | (get_bits(gb, 8) != 'i') || (get_bits(gb, 8) != 's')) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis id header packet corrupt (no vorbis signature). \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis id header packet corrupt (no vorbis signature). \n"); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
vc->version = get_bits_long(gb, 32); //FIXME check 0 | vc->version = get_bits_long(gb, 32); //FIXME check 0 | ||||
vc->audio_channels = get_bits(gb, 8); | vc->audio_channels = get_bits(gb, 8); | ||||
if (vc->audio_channels <= 0) { | if (vc->audio_channels <= 0) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, "Invalid number of channels\n"); | av_log(vc->avccontext, AV_LOG_ERROR, "Invalid number of channels\n"); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
vc->audio_samplerate = get_bits_long(gb, 32); | vc->audio_samplerate = get_bits_long(gb, 32); | ||||
if (vc->audio_samplerate <= 0) { | if (vc->audio_samplerate <= 0) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, "Invalid samplerate\n"); | av_log(vc->avccontext, AV_LOG_ERROR, "Invalid samplerate\n"); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
vc->bitrate_maximum = get_bits_long(gb, 32); | vc->bitrate_maximum = get_bits_long(gb, 32); | ||||
vc->bitrate_nominal = get_bits_long(gb, 32); | vc->bitrate_nominal = get_bits_long(gb, 32); | ||||
@@ -925,20 +938,14 @@ static int vorbis_parse_id_hdr(vorbis_context *vc) | |||||
vc->blocksize[1] = (1 << bl1); | vc->blocksize[1] = (1 << bl1); | ||||
if (bl0 > 13 || bl0 < 6 || bl1 > 13 || bl1 < 6 || bl1 < bl0) { | if (bl0 > 13 || bl0 < 6 || bl1 > 13 || bl1 < 6 || bl1 < bl0) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis id header packet corrupt (illegal blocksize). \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis id header packet corrupt (illegal blocksize). \n"); | ||||
return -3; | |||||
} | |||||
// output format int16 | |||||
if (vc->blocksize[1] / 2 * vc->audio_channels * 2 > AVCODEC_MAX_AUDIO_FRAME_SIZE) { | |||||
av_log(vc->avccontext, AV_LOG_ERROR, "Vorbis channel count makes " | |||||
"output packets too large.\n"); | |||||
return -4; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
vc->win[0] = ff_vorbis_vwin[bl0 - 6]; | vc->win[0] = ff_vorbis_vwin[bl0 - 6]; | ||||
vc->win[1] = ff_vorbis_vwin[bl1 - 6]; | vc->win[1] = ff_vorbis_vwin[bl1 - 6]; | ||||
if ((get_bits1(gb)) == 0) { | if ((get_bits1(gb)) == 0) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis id header packet corrupt (framing flag not set). \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " Vorbis id header packet corrupt (framing flag not set). \n"); | ||||
return -2; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
vc->channel_residues = av_malloc((vc->blocksize[1] / 2) * vc->audio_channels * sizeof(*vc->channel_residues)); | vc->channel_residues = av_malloc((vc->blocksize[1] / 2) * vc->audio_channels * sizeof(*vc->channel_residues)); | ||||
@@ -972,7 +979,7 @@ static av_cold int vorbis_decode_init(AVCodecContext *avccontext) | |||||
uint8_t *header_start[3]; | uint8_t *header_start[3]; | ||||
int header_len[3]; | int header_len[3]; | ||||
GetBitContext *gb = &(vc->gb); | GetBitContext *gb = &(vc->gb); | ||||
int hdr_type; | |||||
int hdr_type, ret; | |||||
vc->avccontext = avccontext; | vc->avccontext = avccontext; | ||||
dsputil_init(&vc->dsp, avccontext); | dsputil_init(&vc->dsp, avccontext); | ||||
@@ -988,24 +995,24 @@ static av_cold int vorbis_decode_init(AVCodecContext *avccontext) | |||||
if (!headers_len) { | if (!headers_len) { | ||||
av_log(avccontext, AV_LOG_ERROR, "Extradata missing.\n"); | av_log(avccontext, AV_LOG_ERROR, "Extradata missing.\n"); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
if (avpriv_split_xiph_headers(headers, headers_len, 30, header_start, header_len) < 0) { | |||||
if ((ret = avpriv_split_xiph_headers(headers, headers_len, 30, header_start, header_len)) < 0) { | |||||
av_log(avccontext, AV_LOG_ERROR, "Extradata corrupt.\n"); | av_log(avccontext, AV_LOG_ERROR, "Extradata corrupt.\n"); | ||||
return -1; | |||||
return ret; | |||||
} | } | ||||
init_get_bits(gb, header_start[0], header_len[0]*8); | init_get_bits(gb, header_start[0], header_len[0]*8); | ||||
hdr_type = get_bits(gb, 8); | hdr_type = get_bits(gb, 8); | ||||
if (hdr_type != 1) { | if (hdr_type != 1) { | ||||
av_log(avccontext, AV_LOG_ERROR, "First header is not the id header.\n"); | av_log(avccontext, AV_LOG_ERROR, "First header is not the id header.\n"); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
if (vorbis_parse_id_hdr(vc)) { | |||||
if ((ret = vorbis_parse_id_hdr(vc))) { | |||||
av_log(avccontext, AV_LOG_ERROR, "Id header corrupt.\n"); | av_log(avccontext, AV_LOG_ERROR, "Id header corrupt.\n"); | ||||
vorbis_free(vc); | vorbis_free(vc); | ||||
return -1; | |||||
return ret; | |||||
} | } | ||||
init_get_bits(gb, header_start[2], header_len[2]*8); | init_get_bits(gb, header_start[2], header_len[2]*8); | ||||
@@ -1013,12 +1020,12 @@ static av_cold int vorbis_decode_init(AVCodecContext *avccontext) | |||||
if (hdr_type != 5) { | if (hdr_type != 5) { | ||||
av_log(avccontext, AV_LOG_ERROR, "Third header is not the setup header.\n"); | av_log(avccontext, AV_LOG_ERROR, "Third header is not the setup header.\n"); | ||||
vorbis_free(vc); | vorbis_free(vc); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
if (vorbis_parse_setup_hdr(vc)) { | |||||
if ((ret = vorbis_parse_setup_hdr(vc))) { | |||||
av_log(avccontext, AV_LOG_ERROR, "Setup header corrupt.\n"); | av_log(avccontext, AV_LOG_ERROR, "Setup header corrupt.\n"); | ||||
vorbis_free(vc); | vorbis_free(vc); | ||||
return -1; | |||||
return ret; | |||||
} | } | ||||
if (vc->audio_channels > 8) | if (vc->audio_channels > 8) | ||||
@@ -1061,7 +1068,7 @@ static int vorbis_floor0_decode(vorbis_context *vc, | |||||
codebook = vc->codebooks[vf->book_list[book_idx]]; | codebook = vc->codebooks[vf->book_list[book_idx]]; | ||||
/* Invalid codebook! */ | /* Invalid codebook! */ | ||||
if (!codebook.codevectors) | if (!codebook.codevectors) | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
while (lsp_len<vf->order) { | while (lsp_len<vf->order) { | ||||
int vec_off; | int vec_off; | ||||
@@ -1427,7 +1434,7 @@ static inline int vorbis_residue_decode(vorbis_context *vc, vorbis_residue *vr, | |||||
return vorbis_residue_decode_internal(vc, vr, ch, do_not_decode, vec, vlen, 0); | return vorbis_residue_decode_internal(vc, vr, ch, do_not_decode, vec, vlen, 0); | ||||
else { | else { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, " Invalid residue type while residue decode?! \n"); | av_log(vc->avccontext, AV_LOG_ERROR, " Invalid residue type while residue decode?! \n"); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
} | } | ||||
@@ -1475,7 +1482,7 @@ static int vorbis_parse_audio_packet(vorbis_context *vc) | |||||
if (get_bits1(gb)) { | if (get_bits1(gb)) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, "Not a Vorbis I audio packet.\n"); | av_log(vc->avccontext, AV_LOG_ERROR, "Not a Vorbis I audio packet.\n"); | ||||
return -1; // packet type not audio | |||||
return AVERROR_INVALIDDATA; // packet type not audio | |||||
} | } | ||||
if (vc->mode_count == 1) { | if (vc->mode_count == 1) { | ||||
@@ -1512,7 +1519,7 @@ static int vorbis_parse_audio_packet(vorbis_context *vc) | |||||
if (ret < 0) { | if (ret < 0) { | ||||
av_log(vc->avccontext, AV_LOG_ERROR, "Invalid codebook in vorbis_floor_decode.\n"); | av_log(vc->avccontext, AV_LOG_ERROR, "Invalid codebook in vorbis_floor_decode.\n"); | ||||
return -1; | |||||
return AVERROR_INVALIDDATA; | |||||
} | } | ||||
no_residue[i] = ret; | no_residue[i] = ret; | ||||
ch_floor_ptr += blocksize / 2; | ch_floor_ptr += blocksize / 2; | ||||
@@ -1613,19 +1620,12 @@ static int vorbis_decode_frame(AVCodecContext *avccontext, | |||||
const float *channel_ptrs[255]; | const float *channel_ptrs[255]; | ||||
int i, len, out_size; | int i, len, out_size; | ||||
if (!buf_size) | |||||
return 0; | |||||
av_dlog(NULL, "packet length %d \n", buf_size); | av_dlog(NULL, "packet length %d \n", buf_size); | ||||
init_get_bits(gb, buf, buf_size*8); | init_get_bits(gb, buf, buf_size*8); | ||||
len = vorbis_parse_audio_packet(vc); | |||||
if (len <= 0) { | |||||
*data_size = 0; | |||||
return buf_size; | |||||
} | |||||
if ((len = vorbis_parse_audio_packet(vc)) <= 0) | |||||
return len; | |||||
if (!vc->first_frame) { | if (!vc->first_frame) { | ||||
vc->first_frame = 1; | vc->first_frame = 1; | ||||
@@ -75,8 +75,11 @@ int ff_avc_parse_nal_units(AVIOContext *pb, const uint8_t *buf_in, int size) | |||||
size = 0; | size = 0; | ||||
nal_start = ff_avc_find_startcode(p, end); | nal_start = ff_avc_find_startcode(p, end); | ||||
while (nal_start < end) { | |||||
while(!*(nal_start++)); | |||||
for (;;) { | |||||
while (nal_start < end && !*(nal_start++)); | |||||
if (nal_start == end) | |||||
break; | |||||
nal_end = ff_avc_find_startcode(nal_start, end); | nal_end = ff_avc_find_startcode(nal_start, end); | ||||
avio_wb32(pb, nal_end - nal_start); | avio_wb32(pb, nal_end - nal_start); | ||||
avio_write(pb, nal_start, nal_end - nal_start); | avio_write(pb, nal_start, nal_end - nal_start); | ||||
@@ -117,22 +120,26 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) | |||||
end = buf + len; | end = buf + len; | ||||
/* look for sps and pps */ | /* look for sps and pps */ | ||||
while (buf < end) { | |||||
unsigned int size; | |||||
while (end - buf > 4) { | |||||
uint32_t size; | |||||
uint8_t nal_type; | uint8_t nal_type; | ||||
size = AV_RB32(buf); | |||||
nal_type = buf[4] & 0x1f; | |||||
size = FFMIN(AV_RB32(buf), end - buf - 4); | |||||
buf += 4; | |||||
nal_type = buf[0] & 0x1f; | |||||
if (nal_type == 7) { /* SPS */ | if (nal_type == 7) { /* SPS */ | ||||
sps = buf + 4; | |||||
sps = buf; | |||||
sps_size = size; | sps_size = size; | ||||
} else if (nal_type == 8) { /* PPS */ | } else if (nal_type == 8) { /* PPS */ | ||||
pps = buf + 4; | |||||
pps = buf; | |||||
pps_size = size; | pps_size = size; | ||||
} | } | ||||
buf += size + 4; | |||||
buf += size; | |||||
} | } | ||||
assert(sps); | |||||
assert(pps); | |||||
if (!sps || !pps || sps_size < 4 || sps_size > UINT16_MAX || pps_size > UINT16_MAX) | |||||
return AVERROR_INVALIDDATA; | |||||
avio_w8(pb, 1); /* version */ | avio_w8(pb, 1); /* version */ | ||||
avio_w8(pb, sps[1]); /* profile */ | avio_w8(pb, sps[1]); /* profile */ | ||||
@@ -338,8 +338,11 @@ int ffurl_close(URLContext *h) | |||||
#if CONFIG_NETWORK | #if CONFIG_NETWORK | ||||
ff_network_close(); | ff_network_close(); | ||||
#endif | #endif | ||||
if (h->prot->priv_data_size) | |||||
if (h->prot->priv_data_size) { | |||||
if (h->prot->priv_data_class) | |||||
av_opt_free(h->priv_data); | |||||
av_free(h->priv_data); | av_free(h->priv_data); | ||||
} | |||||
av_free(h); | av_free(h); | ||||
return ret; | return ret; | ||||
} | } | ||||
@@ -45,9 +45,10 @@ typedef struct { | |||||
} CryptoContext; | } CryptoContext; | ||||
#define OFFSET(x) offsetof(CryptoContext, x) | #define OFFSET(x) offsetof(CryptoContext, x) | ||||
#define D AV_OPT_FLAG_DECODING_PARAM | |||||
static const AVOption options[] = { | static const AVOption options[] = { | ||||
{"key", "AES decryption key", OFFSET(key), AV_OPT_TYPE_BINARY }, | |||||
{"iv", "AES decryption initialization vector", OFFSET(iv), AV_OPT_TYPE_BINARY }, | |||||
{"key", "AES decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, .flags = D }, | |||||
{"iv", "AES decryption initialization vector", OFFSET(iv), AV_OPT_TYPE_BINARY, .flags = D }, | |||||
{ NULL } | { NULL } | ||||
}; | }; | ||||
@@ -61,7 +62,7 @@ static const AVClass crypto_class = { | |||||
static int crypto_open(URLContext *h, const char *uri, int flags) | static int crypto_open(URLContext *h, const char *uri, int flags) | ||||
{ | { | ||||
const char *nested_url; | const char *nested_url; | ||||
int ret; | |||||
int ret = 0; | |||||
CryptoContext *c = h->priv_data; | CryptoContext *c = h->priv_data; | ||||
if (!av_strstart(uri, "crypto+", &nested_url) && | if (!av_strstart(uri, "crypto+", &nested_url) && | ||||
@@ -95,10 +96,7 @@ static int crypto_open(URLContext *h, const char *uri, int flags) | |||||
h->is_streamed = 1; | h->is_streamed = 1; | ||||
return 0; | |||||
err: | err: | ||||
av_freep(&c->key); | |||||
av_freep(&c->iv); | |||||
return ret; | return ret; | ||||
} | } | ||||
@@ -157,8 +155,6 @@ static int crypto_close(URLContext *h) | |||||
if (c->hd) | if (c->hd) | ||||
ffurl_close(c->hd); | ffurl_close(c->hd); | ||||
av_freep(&c->aes); | av_freep(&c->aes); | ||||
av_freep(&c->key); | |||||
av_freep(&c->iv); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -47,36 +47,33 @@ typedef struct { | |||||
int64_t off, filesize; | int64_t off, filesize; | ||||
char location[MAX_URL_SIZE]; | char location[MAX_URL_SIZE]; | ||||
HTTPAuthState auth_state; | HTTPAuthState auth_state; | ||||
unsigned char headers[BUFFER_SIZE]; | |||||
char *headers; | |||||
int willclose; /**< Set if the server correctly handles Connection: close and will close the connection after feeding us the content. */ | int willclose; /**< Set if the server correctly handles Connection: close and will close the connection after feeding us the content. */ | ||||
int chunked_post; | |||||
} HTTPContext; | } HTTPContext; | ||||
#define OFFSET(x) offsetof(HTTPContext, x) | #define OFFSET(x) offsetof(HTTPContext, x) | ||||
#define D AV_OPT_FLAG_DECODING_PARAM | |||||
#define E AV_OPT_FLAG_ENCODING_PARAM | |||||
static const AVOption options[] = { | static const AVOption options[] = { | ||||
{"chunksize", "use chunked transfer-encoding for posts, -1 disables it, 0 enables it", OFFSET(chunksize), AV_OPT_TYPE_INT64, {.dbl = 0}, -1, 0 }, /* Default to 0, for chunked POSTs */ | |||||
{"chunked_post", "use chunked transfer-encoding for posts", OFFSET(chunked_post), AV_OPT_TYPE_INT, {.dbl = 1}, 0, 1, E }, | |||||
{"headers", "custom HTTP headers, can override built in default headers", OFFSET(headers), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E }, | |||||
{NULL} | {NULL} | ||||
}; | }; | ||||
static const AVClass httpcontext_class = { | |||||
.class_name = "HTTP", | |||||
.item_name = av_default_item_name, | |||||
.option = options, | |||||
.version = LIBAVUTIL_VERSION_INT, | |||||
#define HTTP_CLASS(flavor)\ | |||||
static const AVClass flavor ## _context_class = {\ | |||||
.class_name = #flavor,\ | |||||
.item_name = av_default_item_name,\ | |||||
.option = options,\ | |||||
.version = LIBAVUTIL_VERSION_INT,\ | |||||
}; | }; | ||||
HTTP_CLASS(http); | |||||
HTTP_CLASS(https); | |||||
static int http_connect(URLContext *h, const char *path, const char *hoststr, | static int http_connect(URLContext *h, const char *path, const char *hoststr, | ||||
const char *auth, int *new_location); | const char *auth, int *new_location); | ||||
void ff_http_set_headers(URLContext *h, const char *headers) | |||||
{ | |||||
HTTPContext *s = h->priv_data; | |||||
int len = strlen(headers); | |||||
if (len && strcmp("\r\n", headers + len - 2)) | |||||
av_log(h, AV_LOG_ERROR, "No trailing CRLF found in HTTP header.\n"); | |||||
av_strlcpy(s->headers, headers, sizeof(s->headers)); | |||||
} | |||||
void ff_http_init_auth_state(URLContext *dest, const URLContext *src) | void ff_http_init_auth_state(URLContext *dest, const URLContext *src) | ||||
{ | { | ||||
memcpy(&((HTTPContext*)dest->priv_data)->auth_state, | memcpy(&((HTTPContext*)dest->priv_data)->auth_state, | ||||
@@ -168,6 +165,12 @@ static int http_open(URLContext *h, const char *uri, int flags) | |||||
s->filesize = -1; | s->filesize = -1; | ||||
av_strlcpy(s->location, uri, sizeof(s->location)); | av_strlcpy(s->location, uri, sizeof(s->location)); | ||||
if (s->headers) { | |||||
int len = strlen(s->headers); | |||||
if (len < 2 || strcmp("\r\n", s->headers + len - 2)) | |||||
av_log(h, AV_LOG_WARNING, "No trailing CRLF found in HTTP header.\n"); | |||||
} | |||||
return http_open_cnx(h); | return http_open_cnx(h); | ||||
} | } | ||||
static int http_getc(HTTPContext *s) | static int http_getc(HTTPContext *s) | ||||
@@ -285,6 +288,8 @@ static int process_line(URLContext *h, char *line, int line_count, | |||||
static inline int has_header(const char *str, const char *header) | static inline int has_header(const char *str, const char *header) | ||||
{ | { | ||||
/* header + 2 to skip over CRLF prefix. (make sure you have one!) */ | /* header + 2 to skip over CRLF prefix. (make sure you have one!) */ | ||||
if (!str) | |||||
return 0; | |||||
return av_stristart(str, header + 2, NULL) || av_stristr(str, header); | return av_stristart(str, header + 2, NULL) || av_stristr(str, header); | ||||
} | } | ||||
@@ -312,7 +317,7 @@ static int http_connect(URLContext *h, const char *path, const char *hoststr, | |||||
if (!has_header(s->headers, "\r\nAccept: ")) | if (!has_header(s->headers, "\r\nAccept: ")) | ||||
len += av_strlcpy(headers + len, "Accept: */*\r\n", | len += av_strlcpy(headers + len, "Accept: */*\r\n", | ||||
sizeof(headers) - len); | sizeof(headers) - len); | ||||
if (!has_header(s->headers, "\r\nRange: ")) | |||||
if (!has_header(s->headers, "\r\nRange: ") && !post) | |||||
len += av_strlcatf(headers + len, sizeof(headers) - len, | len += av_strlcatf(headers + len, sizeof(headers) - len, | ||||
"Range: bytes=%"PRId64"-\r\n", s->off); | "Range: bytes=%"PRId64"-\r\n", s->off); | ||||
if (!has_header(s->headers, "\r\nConnection: ")) | if (!has_header(s->headers, "\r\nConnection: ")) | ||||
@@ -323,7 +328,8 @@ static int http_connect(URLContext *h, const char *path, const char *hoststr, | |||||
"Host: %s\r\n", hoststr); | "Host: %s\r\n", hoststr); | ||||
/* now add in custom headers */ | /* now add in custom headers */ | ||||
av_strlcpy(headers+len, s->headers, sizeof(headers)-len); | |||||
if (s->headers) | |||||
av_strlcpy(headers + len, s->headers, sizeof(headers) - len); | |||||
snprintf(s->buffer, sizeof(s->buffer), | snprintf(s->buffer, sizeof(s->buffer), | ||||
"%s %s HTTP/1.1\r\n" | "%s %s HTTP/1.1\r\n" | ||||
@@ -333,7 +339,7 @@ static int http_connect(URLContext *h, const char *path, const char *hoststr, | |||||
"\r\n", | "\r\n", | ||||
post ? "POST" : "GET", | post ? "POST" : "GET", | ||||
path, | path, | ||||
post && s->chunksize >= 0 ? "Transfer-Encoding: chunked\r\n" : "", | |||||
post && s->chunked_post ? "Transfer-Encoding: chunked\r\n" : "", | |||||
headers, | headers, | ||||
authstr ? authstr : ""); | authstr ? authstr : ""); | ||||
@@ -430,7 +436,7 @@ static int http_write(URLContext *h, const uint8_t *buf, int size) | |||||
char crlf[] = "\r\n"; | char crlf[] = "\r\n"; | ||||
HTTPContext *s = h->priv_data; | HTTPContext *s = h->priv_data; | ||||
if (s->chunksize == -1) { | |||||
if (!s->chunked_post) { | |||||
/* non-chunked data is sent without any special encoding */ | /* non-chunked data is sent without any special encoding */ | ||||
return ffurl_write(s->hd, buf, size); | return ffurl_write(s->hd, buf, size); | ||||
} | } | ||||
@@ -456,7 +462,7 @@ static int http_close(URLContext *h) | |||||
HTTPContext *s = h->priv_data; | HTTPContext *s = h->priv_data; | ||||
/* signal end of chunked encoding if used */ | /* signal end of chunked encoding if used */ | ||||
if ((h->flags & AVIO_FLAG_WRITE) && s->chunksize != -1) { | |||||
if ((h->flags & AVIO_FLAG_WRITE) && s->chunked_post) { | |||||
ret = ffurl_write(s->hd, footer, sizeof(footer) - 1); | ret = ffurl_write(s->hd, footer, sizeof(footer) - 1); | ||||
ret = ret > 0 ? 0 : ret; | ret = ret > 0 ? 0 : ret; | ||||
} | } | ||||
@@ -519,7 +525,7 @@ URLProtocol ff_http_protocol = { | |||||
.url_close = http_close, | .url_close = http_close, | ||||
.url_get_file_handle = http_get_file_handle, | .url_get_file_handle = http_get_file_handle, | ||||
.priv_data_size = sizeof(HTTPContext), | .priv_data_size = sizeof(HTTPContext), | ||||
.priv_data_class = &httpcontext_class, | |||||
.priv_data_class = &http_context_class, | |||||
}; | }; | ||||
#endif | #endif | ||||
#if CONFIG_HTTPS_PROTOCOL | #if CONFIG_HTTPS_PROTOCOL | ||||
@@ -532,6 +538,6 @@ URLProtocol ff_https_protocol = { | |||||
.url_close = http_close, | .url_close = http_close, | ||||
.url_get_file_handle = http_get_file_handle, | .url_get_file_handle = http_get_file_handle, | ||||
.priv_data_size = sizeof(HTTPContext), | .priv_data_size = sizeof(HTTPContext), | ||||
.priv_data_class = &httpcontext_class, | |||||
.priv_data_class = &https_context_class, | |||||
}; | }; | ||||
#endif | #endif |
@@ -24,24 +24,6 @@ | |||||
#include "url.h" | #include "url.h" | ||||
/** | |||||
* Set custom HTTP headers. | |||||
* A trailing CRLF ("\r\n") is required for custom headers. | |||||
* Passing in an empty header string ("\0") will reset to defaults. | |||||
* | |||||
* The following headers can be overriden by custom values, | |||||
* otherwise they will be set to their defaults. | |||||
* -User-Agent | |||||
* -Accept | |||||
* -Range | |||||
* -Host | |||||
* -Connection | |||||
* | |||||
* @param h URL context for this HTTP connection | |||||
* @param headers the custom headers to set | |||||
*/ | |||||
void ff_http_set_headers(URLContext *h, const char *headers); | |||||
/** | /** | ||||
* Initialize the authentication state based on another HTTP URLContext. | * Initialize the authentication state based on another HTTP URLContext. | ||||
* This can be used to pre-initialize the authentication parameters if | * This can be used to pre-initialize the authentication parameters if | ||||
@@ -28,6 +28,7 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#include "libavutil/intreadwrite.h" | #include "libavutil/intreadwrite.h" | ||||
#include "libavutil/avstring.h" | #include "libavutil/avstring.h" | ||||
#include "libavutil/opt.h" | |||||
#include "internal.h" | #include "internal.h" | ||||
#include "mms.h" | #include "mms.h" | ||||
#include "asf.h" | #include "asf.h" | ||||
@@ -246,7 +247,7 @@ static int mmsh_open_internal(URLContext *h, const char *uri, int flags, int tim | |||||
CLIENTGUID | CLIENTGUID | ||||
"Connection: Close\r\n", | "Connection: Close\r\n", | ||||
host, port, mmsh->request_seq++); | host, port, mmsh->request_seq++); | ||||
ff_http_set_headers(mms->mms_hd, headers); | |||||
av_opt_set(mms->mms_hd->priv_data, "headers", headers, 0); | |||||
err = ffurl_connect(mms->mms_hd); | err = ffurl_connect(mms->mms_hd); | ||||
if (err) { | if (err) { | ||||
@@ -293,7 +294,7 @@ static int mmsh_open_internal(URLContext *h, const char *uri, int flags, int tim | |||||
goto fail; | goto fail; | ||||
} | } | ||||
av_dlog(NULL, "out_buffer is %s", headers); | av_dlog(NULL, "out_buffer is %s", headers); | ||||
ff_http_set_headers(mms->mms_hd, headers); | |||||
av_opt_set(mms->mms_hd->priv_data, "headers", headers, 0); | |||||
err = ffurl_connect(mms->mms_hd); | err = ffurl_connect(mms->mms_hd); | ||||
if (err) { | if (err) { | ||||
@@ -1462,7 +1462,7 @@ redirect: | |||||
"Pragma: no-cache\r\n" | "Pragma: no-cache\r\n" | ||||
"Cache-Control: no-cache\r\n", | "Cache-Control: no-cache\r\n", | ||||
sessioncookie); | sessioncookie); | ||||
ff_http_set_headers(rt->rtsp_hd, headers); | |||||
av_opt_set(rt->rtsp_hd->priv_data, "headers", headers, 0); | |||||
/* complete the connection */ | /* complete the connection */ | ||||
if (ffurl_connect(rt->rtsp_hd)) { | if (ffurl_connect(rt->rtsp_hd)) { | ||||
@@ -1485,8 +1485,8 @@ redirect: | |||||
"Content-Length: 32767\r\n" | "Content-Length: 32767\r\n" | ||||
"Expires: Sun, 9 Jan 1972 00:00:00 GMT\r\n", | "Expires: Sun, 9 Jan 1972 00:00:00 GMT\r\n", | ||||
sessioncookie); | sessioncookie); | ||||
ff_http_set_headers(rt->rtsp_hd_out, headers); | |||||
av_opt_set(rt->rtsp_hd_out->priv_data, "chunksize", "-1", 0); | |||||
av_opt_set(rt->rtsp_hd_out->priv_data, "headers", headers, 0); | |||||
av_opt_set(rt->rtsp_hd_out->priv_data, "chunked_post", "0", 0); | |||||
/* Initialize the authentication state for the POST session. The HTTP | /* Initialize the authentication state for the POST session. The HTTP | ||||
* protocol implementation doesn't properly handle multi-pass | * protocol implementation doesn't properly handle multi-pass | ||||
@@ -73,7 +73,7 @@ static int do_tls_poll(URLContext *h, int ret) | |||||
struct pollfd p = { c->fd, 0, 0 }; | struct pollfd p = { c->fd, 0, 0 }; | ||||
#if CONFIG_GNUTLS | #if CONFIG_GNUTLS | ||||
if (ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED) { | if (ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED) { | ||||
av_log(NULL, AV_LOG_ERROR, "%s\n", gnutls_strerror(ret)); | |||||
av_log(h, AV_LOG_ERROR, "%s\n", gnutls_strerror(ret)); | |||||
return AVERROR(EIO); | return AVERROR(EIO); | ||||
} | } | ||||
if (gnutls_record_get_direction(c->session)) | if (gnutls_record_get_direction(c->session)) | ||||
@@ -87,11 +87,11 @@ static int do_tls_poll(URLContext *h, int ret) | |||||
} else if (ret == SSL_ERROR_WANT_WRITE) { | } else if (ret == SSL_ERROR_WANT_WRITE) { | ||||
p.events = POLLOUT; | p.events = POLLOUT; | ||||
} else { | } else { | ||||
av_log(NULL, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); | |||||
av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); | |||||
return AVERROR(EIO); | return AVERROR(EIO); | ||||
} | } | ||||
#endif | #endif | ||||
if (h->flags & URL_FLAG_NONBLOCK) | |||||
if (h->flags & AVIO_FLAG_NONBLOCK) | |||||
return AVERROR(EAGAIN); | return AVERROR(EAGAIN); | ||||
while (1) { | while (1) { | ||||
int n = poll(&p, 1, 100); | int n = poll(&p, 1, 100); | ||||
@@ -148,13 +148,13 @@ static int tls_open(URLContext *h, const char *uri, int flags) | |||||
#elif CONFIG_OPENSSL | #elif CONFIG_OPENSSL | ||||
c->ctx = SSL_CTX_new(SSLv3_client_method()); | c->ctx = SSL_CTX_new(SSLv3_client_method()); | ||||
if (!c->ctx) { | if (!c->ctx) { | ||||
av_log(NULL, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); | |||||
av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); | |||||
ret = AVERROR(EIO); | ret = AVERROR(EIO); | ||||
goto fail; | goto fail; | ||||
} | } | ||||
c->ssl = SSL_new(c->ctx); | c->ssl = SSL_new(c->ctx); | ||||
if (!c->ssl) { | if (!c->ssl) { | ||||
av_log(NULL, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); | |||||
av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); | |||||
ret = AVERROR(EIO); | ret = AVERROR(EIO); | ||||
goto fail; | goto fail; | ||||
} | } | ||||
@@ -166,7 +166,7 @@ static int tls_open(URLContext *h, const char *uri, int flags) | |||||
if (ret > 0) | if (ret > 0) | ||||
break; | break; | ||||
if (ret == 0) { | if (ret == 0) { | ||||
av_log(NULL, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n"); | |||||
av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n"); | |||||
ret = AVERROR(EIO); | ret = AVERROR(EIO); | ||||
goto fail; | goto fail; | ||||
} | } | ||||
@@ -222,11 +222,9 @@ int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt) | |||||
a->rounds = rounds; | a->rounds = rounds; | ||||
memcpy(tk, key, KC * 4); | memcpy(tk, key, KC * 4); | ||||
memcpy(a->round_key[0].u8, key, KC * 4); | |||||
for (t = 0; t < (rounds + 1) * 16;) { | |||||
memcpy(a->round_key[0].u8 + t, tk, KC * 4); | |||||
t += KC * 4; | |||||
for (t = KC * 4; t < (rounds + 1) * 16; t += KC * 4) { | |||||
for (i = 0; i < 4; i++) | for (i = 0; i < 4; i++) | ||||
tk[0][i] ^= sbox[tk[KC - 1][(i + 1) & 3]]; | tk[0][i] ^= sbox[tk[KC - 1][(i + 1) & 3]]; | ||||
tk[0][0] ^= rcon[rconpointer++]; | tk[0][0] ^= rcon[rconpointer++]; | ||||
@@ -239,6 +237,8 @@ int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt) | |||||
for (i = 0; i < 4; i++) | for (i = 0; i < 4; i++) | ||||
tk[j][i] ^= sbox[tk[j - 1][i]]; | tk[j][i] ^= sbox[tk[j - 1][i]]; | ||||
} | } | ||||
memcpy(a->round_key[0].u8 + t, tk, KC * 4); | |||||
} | } | ||||
if (decrypt) { | if (decrypt) { | ||||