diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2011-09-25 23:30:25 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-09-25 23:30:25 +0200 |
commit | 537a9e5cc28fe55deedc30953737cff124ac570f (patch) | |
tree | 3ebcc12011b67905d09f439dc85421cb1834927c /libavcodec | |
parent | 508e47a5751b063e5b3d1d6aceda8a19ad8b1d37 (diff) | |
parent | d853e571ad5e7e12c6a68cfde390daced7d85fbb (diff) | |
download | ffmpeg-537a9e5cc28fe55deedc30953737cff124ac570f.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master:
ppc: fix some pointer to integer casts
ppc: fix 32-bit PIC build
vmdaudio: fix decoding of 16-bit audio format.
lavf: do not set codec_tag for rawvideo
h264: check for out of bounds reads in ff_h264_decode_extradata().
flvdec: Check for overflow before allocating arrays
avconv: use correct output stream index when checking max_frames
avconv: remove fake coded_frame on streamcopy hack
Conflicts:
avconv.c
libavcodec/h264.c
libavcodec/ppc/asm.S
libavcodec/vmdav.c
libavformat/flvdec.c
libavformat/utils.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/ppc/asm.S | 23 | ||||
-rw-r--r-- | libavcodec/ppc/fft_altivec_s.S | 7 | ||||
-rw-r--r-- | libavcodec/vmdav.c | 121 |
3 files changed, 99 insertions, 52 deletions
diff --git a/libavcodec/ppc/asm.S b/libavcodec/ppc/asm.S index 2706d6b1d8..bbbf8a4a66 100644 --- a/libavcodec/ppc/asm.S +++ b/libavcodec/ppc/asm.S @@ -44,10 +44,13 @@ X(\name): L(\name): .endm -.macro movrel rd, sym +.macro movrel rd, sym, gp ld \rd, \sym@got(r2) .endm +.macro get_got rd +.endm + #else /* ARCH_PPC64 */ #define PTR .int @@ -65,19 +68,25 @@ X(\name): \name: .endm -.macro movrel rd, sym +.macro movrel rd, sym, gp #if CONFIG_PIC - bcl 20, 31, lab_pic_\@ -lab_pic_\@: - mflr \rd - addis \rd, \rd, (\sym - lab_pic_\@)@ha - addi \rd, \rd, (\sym - lab_pic_\@)@l + lwz \rd, \sym@got(\gp) #else lis \rd, \sym@ha la \rd, \sym@l(\rd) #endif .endm +.macro get_got rd +#if CONFIG_PIC + bcl 20, 31, .Lgot\@ +.Lgot\@: + mflr \rd + addis \rd, \rd, _GLOBAL_OFFSET_TABLE_ - .Lgot\@@ha + addi \rd, \rd, _GLOBAL_OFFSET_TABLE_ - .Lgot\@@l +#endif +.endm + #endif /* ARCH_PPC64 */ #if HAVE_IBM_ASM diff --git a/libavcodec/ppc/fft_altivec_s.S b/libavcodec/ppc/fft_altivec_s.S index 5d3c5406c3..16ce838c97 100644 --- a/libavcodec/ppc/fft_altivec_s.S +++ b/libavcodec/ppc/fft_altivec_s.S @@ -353,6 +353,7 @@ extfunc ff_fft_calc\interleave\()_altivec mflr r0 stp r0, 2*PS(r1) stpu r1, -(160+16*PS)(r1) + get_got r11 addi r6, r1, 16*PS stvm r6, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29 mfvrsave r0 @@ -360,14 +361,14 @@ extfunc ff_fft_calc\interleave\()_altivec li r6, 0xfffffffc mtvrsave r6 - movrel r6, fft_data + movrel r6, fft_data, r11 lvm r6, v14, v15, v16, v17, v18, v19, v20, v21 lvm r6, v22, v23, v24, v25, v26, v27, v28, v29 li r9, 16 - movrel r12, X(ff_cos_tabs) + movrel r12, X(ff_cos_tabs), r11 - movrel r6, fft_dispatch_tab\interleave\()_altivec + movrel r6, fft_dispatch_tab\interleave\()_altivec, r11 lwz r3, 0(r3) subi r3, r3, 2 slwi r3, r3, 2+ARCH_PPC64 diff --git a/libavcodec/vmdav.c b/libavcodec/vmdav.c index 6729af6af7..63ac33db59 100644 --- a/libavcodec/vmdav.c +++ b/libavcodec/vmdav.c @@ -465,9 +465,8 @@ static av_cold int vmdvideo_decode_end(AVCodecContext *avctx) #define BLOCK_TYPE_SILENCE 3 typedef struct VmdAudioContext { - AVCodecContext *avctx; int out_bps; - int predictors[2]; + int chunk_size; } VmdAudioContext; static const uint16_t vmdaudio_table[128] = { @@ -490,13 +489,23 @@ static av_cold int vmdaudio_decode_init(AVCodecContext *avctx) { VmdAudioContext *s = avctx->priv_data; - s->avctx = avctx; + if (avctx->channels < 1 || avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); + return AVERROR(EINVAL); + } + if (avctx->block_align < 1) { + av_log(avctx, AV_LOG_ERROR, "invalid block align\n"); + return AVERROR(EINVAL); + } + if (avctx->bits_per_coded_sample == 16) avctx->sample_fmt = AV_SAMPLE_FMT_S16; else avctx->sample_fmt = AV_SAMPLE_FMT_U8; s->out_bps = av_get_bytes_per_sample(avctx->sample_fmt); + s->chunk_size = avctx->block_align + avctx->channels * (s->out_bps == 2); + av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, " "block align = %d, sample rate = %d\n", avctx->channels, avctx->bits_per_coded_sample, avctx->block_align, @@ -505,41 +514,33 @@ static av_cold int vmdaudio_decode_init(AVCodecContext *avctx) return 0; } -static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data, - const uint8_t *buf, int buf_size, int stereo) +static void decode_audio_s16(int16_t *out, const uint8_t *buf, int buf_size, + int channels) { - int i; - int chan = 0; - int16_t *out = (int16_t*)data; - - for(i = 0; i < buf_size; i++) { - if(buf[i] & 0x80) - s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F]; - else - s->predictors[chan] += vmdaudio_table[buf[i]]; - s->predictors[chan] = av_clip_int16(s->predictors[chan]); - out[i] = s->predictors[chan]; - chan ^= stereo; + int ch; + const uint8_t *buf_end = buf + buf_size; + int predictor[2]; + int st = channels - 1; + + /* decode initial raw sample */ + for (ch = 0; ch < channels; ch++) { + predictor[ch] = (int16_t)AV_RL16(buf); + buf += 2; + *out++ = predictor[ch]; } -} -static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data, - const uint8_t *buf, int silent_chunks, int data_size) -{ - int silent_size = s->avctx->block_align * silent_chunks * s->out_bps; - - if (silent_chunks) { - memset(data, s->out_bps == 2 ? 0x00 : 0x80, silent_size); - data += silent_size; - } - if (s->avctx->bits_per_coded_sample == 16) - vmdaudio_decode_audio(s, data, buf, data_size, s->avctx->channels == 2); - else { - /* just copy the data */ - memcpy(data, buf, data_size); + /* decode DPCM samples */ + ch = 0; + while (buf < buf_end) { + uint8_t b = *buf++; + if (b & 0x80) + predictor[ch] -= vmdaudio_table[b & 0x7F]; + else + predictor[ch] += vmdaudio_table[b]; + predictor[ch] = av_clip_int16(predictor[ch]); + *out++ = predictor[ch]; + ch ^= st; } - - return silent_size + data_size * s->out_bps; } static int vmdaudio_decode_frame(AVCodecContext *avctx, @@ -547,10 +548,13 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; + const uint8_t *buf_end; int buf_size = avpkt->size; VmdAudioContext *s = avctx->priv_data; - int block_type, silent_chunks; - unsigned char *output_samples = (unsigned char *)data; + int block_type, silent_chunks, audio_chunks; + int nb_samples, out_size; + uint8_t *output_samples_u8 = data; + int16_t *output_samples_s16 = data; if (buf_size < 16) { av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n"); @@ -566,13 +570,16 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, buf += 16; buf_size -= 16; + /* get number of silent chunks */ silent_chunks = 0; if (block_type == BLOCK_TYPE_INITIAL) { uint32_t flags; - if (buf_size < 4) - return -1; - flags = AV_RB32(buf); - silent_chunks = av_popcount(flags); + if (buf_size < 4) { + av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); + return AVERROR(EINVAL); + } + flags = AV_RB32(buf); + silent_chunks = av_popcount(flags); buf += 4; buf_size -= 4; } else if (block_type == BLOCK_TYPE_SILENCE) { @@ -581,11 +588,41 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, } /* ensure output buffer is large enough */ - if (*data_size < (avctx->block_align*silent_chunks + buf_size) * s->out_bps) + audio_chunks = buf_size / s->chunk_size; + nb_samples = ((silent_chunks + audio_chunks) * avctx->block_align) / avctx->channels; + out_size = nb_samples * avctx->channels * s->out_bps; + if (*data_size < out_size) return -1; - *data_size = vmdaudio_loadsound(s, output_samples, buf, silent_chunks, buf_size); + /* decode silent chunks */ + if (silent_chunks > 0) { + int silent_size = avctx->block_align * silent_chunks; + if (s->out_bps == 2) { + memset(output_samples_s16, 0x00, silent_size * 2); + output_samples_s16 += silent_size; + } else { + memset(output_samples_u8, 0x80, silent_size); + output_samples_u8 += silent_size; + } + } + + /* decode audio chunks */ + if (audio_chunks > 0) { + buf_end = buf + buf_size; + while (buf < buf_end) { + if (s->out_bps == 2) { + decode_audio_s16(output_samples_s16, buf, s->chunk_size, + avctx->channels); + output_samples_s16 += avctx->block_align; + } else { + memcpy(output_samples_u8, buf, s->chunk_size); + output_samples_u8 += avctx->block_align; + } + buf += s->chunk_size; + } + } + *data_size = out_size; return avpkt->size; } |