From 221fe9f455762260f77afb05ed7a142640314a7b Mon Sep 17 00:00:00 2001 From: David McPaul Date: Mon, 15 Sep 2008 14:07:05 +0000 Subject: [PATCH] Update avcodec to 20080825 git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27552 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../plugins/avcodec/libavcodec/w32thread.c | 134 +++ .../plugins/avcodec/libavcodec/wavpack.c | 587 +++++++++++ .../media/plugins/avcodec/libavcodec/wma.c | 384 +++++++ .../media/plugins/avcodec/libavcodec/wma.h | 149 +++ .../plugins/avcodec/libavcodec/wmadata.h | 65 +- .../media/plugins/avcodec/libavcodec/wmadec.c | 934 +++++------------- .../media/plugins/avcodec/libavcodec/wmaenc.c | 405 ++++++++ .../media/plugins/avcodec/libavcodec/wmv2.c | 767 +------------- .../media/plugins/avcodec/libavcodec/wmv2.h | 58 ++ .../plugins/avcodec/libavcodec/wmv2dec.c | 496 ++++++++++ .../plugins/avcodec/libavcodec/wmv2enc.c | 241 +++++ .../media/plugins/avcodec/libavcodec/wnv1.c | 145 +++ .../plugins/avcodec/libavcodec/ws-snd1.c | 154 +++ 13 files changed, 3091 insertions(+), 1428 deletions(-) create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/w32thread.c create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/wavpack.c create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/wma.c create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/wma.h create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/wmaenc.c create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/wmv2.h create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/wmv2dec.c create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/wmv2enc.c create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/wnv1.c create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/ws-snd1.c diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/w32thread.c b/src/add-ons/media/plugins/avcodec/libavcodec/w32thread.c new file mode 100644 index 0000000000..5758c692ab --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/w32thread.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +//#define DEBUG + +#include "avcodec.h" + +#define WIN32_LEAN_AND_MEAN +#include +#include + +typedef struct ThreadContext{ + AVCodecContext *avctx; + HANDLE thread; + HANDLE work_sem; + HANDLE done_sem; + int (*func)(AVCodecContext *c, void *arg); + void *arg; + int ret; +}ThreadContext; + + +static unsigned WINAPI attribute_align_arg thread_func(void *v){ + ThreadContext *c= v; + + for(;;){ +//printf("thread_func %X enter wait\n", (int)v); fflush(stdout); + WaitForSingleObject(c->work_sem, INFINITE); +//printf("thread_func %X after wait (func=%X)\n", (int)v, (int)c->func); fflush(stdout); + if(c->func) + c->ret= c->func(c->avctx, c->arg); + else + return 0; +//printf("thread_func %X signal complete\n", (int)v); fflush(stdout); + ReleaseSemaphore(c->done_sem, 1, 0); + } + + return 0; +} + +/** + * Free what has been allocated by avcodec_thread_init(). + * Must be called after decoding has finished, especially do not call while avcodec_thread_execute() is running. + */ +void avcodec_thread_free(AVCodecContext *s){ + ThreadContext *c= s->thread_opaque; + int i; + + for(i=0; ithread_count; i++){ + + c[i].func= NULL; + ReleaseSemaphore(c[i].work_sem, 1, 0); + WaitForSingleObject(c[i].thread, INFINITE); + if(c[i].work_sem) CloseHandle(c[i].work_sem); + if(c[i].done_sem) CloseHandle(c[i].done_sem); + } + + av_freep(&s->thread_opaque); +} + +int avcodec_thread_execute(AVCodecContext *s, int (*func)(AVCodecContext *c2, void *arg2),void **arg, int *ret, int count){ + ThreadContext *c= s->thread_opaque; + int i; + + assert(s == c->avctx); + assert(count <= s->thread_count); + + /* note, we can be certain that this is not called with the same AVCodecContext by different threads at the same time */ + + for(i=0; ithread_count= thread_count; + + assert(!s->thread_opaque); + c= av_mallocz(sizeof(ThreadContext)*thread_count); + s->thread_opaque= c; + + for(i=0; ithread_count, NULL))) + goto fail; + if(!(c[i].done_sem = CreateSemaphore(NULL, 0, s->thread_count, NULL))) + goto fail; + +//printf("create thread %d\n", i); fflush(stdout); + c[i].thread = (HANDLE)_beginthreadex(NULL, 0, thread_func, &c[i], 0, &threadid ); + if( !c[i].thread ) goto fail; + } +//printf("init done\n"); fflush(stdout); + + s->execute= avcodec_thread_execute; + + return 0; +fail: + avcodec_thread_free(s); + return -1; +} diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/wavpack.c b/src/add-ons/media/plugins/avcodec/libavcodec/wavpack.c new file mode 100644 index 0000000000..e8703b38dc --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/wavpack.c @@ -0,0 +1,587 @@ +/* + * WavPack lossless audio decoder + * Copyright (c) 2006 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#define ALT_BITSTREAM_READER_LE +#include "avcodec.h" +#include "bitstream.h" +#include "unary.h" + +/** + * @file wavpack.c + * WavPack lossless audio decoder + */ + +#define WV_JOINT_STEREO 0x00000010 +#define WV_FALSE_STEREO 0x40000000 + +enum WP_ID_Flags{ + WP_IDF_MASK = 0x1F, + WP_IDF_IGNORE = 0x20, + WP_IDF_ODD = 0x40, + WP_IDF_LONG = 0x80 +}; + +enum WP_ID{ + WP_ID_DUMMY = 0, + WP_ID_ENCINFO, + WP_ID_DECTERMS, + WP_ID_DECWEIGHTS, + WP_ID_DECSAMPLES, + WP_ID_ENTROPY, + WP_ID_HYBRID, + WP_ID_SHAPING, + WP_ID_FLOATINFO, + WP_ID_INT32INFO, + WP_ID_DATA, + WP_ID_CORR, + WP_ID_FLT, + WP_ID_CHANINFO +}; + +#define MAX_TERMS 16 + +typedef struct Decorr { + int delta; + int value; + int weightA; + int weightB; + int samplesA[8]; + int samplesB[8]; +} Decorr; + +typedef struct WavpackContext { + AVCodecContext *avctx; + int stereo, stereo_in; + int joint; + uint32_t CRC; + GetBitContext gb; + int data_size; // in bits + int samples; + int median[6]; + int terms; + Decorr decorr[MAX_TERMS]; + int zero, one, zeroes; + int and, or, shift; +} WavpackContext; + +// exponent table copied from WavPack source +static const uint8_t wp_exp2_table [256] = { + 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0b, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15, 0x16, 0x16, + 0x17, 0x18, 0x19, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1f, 0x20, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x24, 0x25, 0x26, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3d, + 0x3e, 0x3f, 0x40, 0x41, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b, + 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, + 0x5b, 0x5c, 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, + 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, + 0x9c, 0x9d, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, + 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, + 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc8, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf, 0xd0, 0xd2, 0xd3, 0xd4, + 0xd6, 0xd7, 0xd8, 0xd9, 0xdb, 0xdc, 0xdd, 0xde, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe8, 0xe9, + 0xea, 0xec, 0xed, 0xee, 0xf0, 0xf1, 0xf2, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xff +}; + +static av_always_inline int wp_exp2(int16_t val) +{ + int res, neg = 0; + + if(val < 0){ + val = -val; + neg = 1; + } + + res = wp_exp2_table[val & 0xFF] | 0x100; + val >>= 8; + res = (val > 9) ? (res << (val - 9)) : (res >> (9 - val)); + return neg ? -res : res; +} + +// macros for manipulating median values +#define GET_MED(n) ((median[n] >> 4) + 1) +#define DEC_MED(n) median[n] -= ((median[n] + (128>>n) - 2) / (128>>n)) * 2 +#define INC_MED(n) median[n] += ((median[n] + (128>>n)) / (128>>n)) * 5 + +// macros for applying weight +#define UPDATE_WEIGHT_CLIP(weight, delta, samples, in) \ + if(samples && in){ \ + if((samples ^ in) < 0){ \ + weight -= delta; \ + if(weight < -1024) weight = -1024; \ + }else{ \ + weight += delta; \ + if(weight > 1024) weight = 1024; \ + } \ + } + + +static av_always_inline int get_tail(GetBitContext *gb, int k) +{ + int p, e, res; + + if(k<1)return 0; + p = av_log2(k); + e = (1 << (p + 1)) - k - 1; + res = p ? get_bits(gb, p) : 0; + if(res >= e){ + res = (res<<1) - e + get_bits1(gb); + } + return res; +} + +static int wv_get_value(WavpackContext *ctx, GetBitContext *gb, int *median, int *last) +{ + int t, t2; + int sign, base, add, ret; + + *last = 0; + + if((ctx->median[0] < 2U) && (ctx->median[3] < 2U) && !ctx->zero && !ctx->one){ + if(ctx->zeroes){ + ctx->zeroes--; + if(ctx->zeroes) + return 0; + }else{ + t = get_unary_0_33(gb); + if(t >= 2) t = get_bits(gb, t - 1) | (1 << (t-1)); + ctx->zeroes = t; + if(ctx->zeroes){ + memset(ctx->median, 0, sizeof(ctx->median)); + return 0; + } + } + } + + if(get_bits_count(gb) >= ctx->data_size){ + *last = 1; + return 0; + } + + if(ctx->zero){ + t = 0; + ctx->zero = 0; + }else{ + t = get_unary_0_33(gb); + if(get_bits_count(gb) >= ctx->data_size){ + *last = 1; + return 0; + } + if(t == 16) { + t2 = get_unary_0_33(gb); + if(t2 < 2) t += t2; + else t += get_bits(gb, t2 - 1) | (1 << (t2 - 1)); + } + + if(ctx->one){ + ctx->one = t&1; + t = (t>>1) + 1; + }else{ + ctx->one = t&1; + t >>= 1; + } + ctx->zero = !ctx->one; + } + + if(!t){ + base = 0; + add = GET_MED(0) - 1; + DEC_MED(0); + }else if(t == 1){ + base = GET_MED(0); + add = GET_MED(1) - 1; + INC_MED(0); + DEC_MED(1); + }else if(t == 2){ + base = GET_MED(0) + GET_MED(1); + add = GET_MED(2) - 1; + INC_MED(0); + INC_MED(1); + DEC_MED(2); + }else{ + base = GET_MED(0) + GET_MED(1) + GET_MED(2) * (t - 2); + add = GET_MED(2) - 1; + INC_MED(0); + INC_MED(1); + INC_MED(2); + } + ret = base + get_tail(gb, add); + sign = get_bits1(gb); + return sign ? ~ret : ret; +} + +static int wv_unpack_stereo(WavpackContext *s, GetBitContext *gb, int16_t *dst) +{ + int i, j, count = 0; + int last, t; + int A, B, L, L2, R, R2, bit; + int pos = 0; + uint32_t crc = 0xFFFFFFFF; + + s->one = s->zero = s->zeroes = 0; + do{ + L = wv_get_value(s, gb, s->median, &last); + if(last) break; + R = wv_get_value(s, gb, s->median + 3, &last); + if(last) break; + for(i = 0; i < s->terms; i++){ + t = s->decorr[i].value; + j = 0; + if(t > 0){ + if(t > 8){ + if(t & 1){ + A = 2 * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1]; + B = 2 * s->decorr[i].samplesB[0] - s->decorr[i].samplesB[1]; + }else{ + A = (3 * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1]) >> 1; + B = (3 * s->decorr[i].samplesB[0] - s->decorr[i].samplesB[1]) >> 1; + } + s->decorr[i].samplesA[1] = s->decorr[i].samplesA[0]; + s->decorr[i].samplesB[1] = s->decorr[i].samplesB[0]; + j = 0; + }else{ + A = s->decorr[i].samplesA[pos]; + B = s->decorr[i].samplesB[pos]; + j = (pos + t) & 7; + } + L2 = L + ((s->decorr[i].weightA * A + 512) >> 10); + R2 = R + ((s->decorr[i].weightB * B + 512) >> 10); + if(A && L) s->decorr[i].weightA -= ((((L ^ A) >> 30) & 2) - 1) * s->decorr[i].delta; + if(B && R) s->decorr[i].weightB -= ((((R ^ B) >> 30) & 2) - 1) * s->decorr[i].delta; + s->decorr[i].samplesA[j] = L = L2; + s->decorr[i].samplesB[j] = R = R2; + }else if(t == -1){ + L2 = L + ((s->decorr[i].weightA * s->decorr[i].samplesA[0] + 512) >> 10); + UPDATE_WEIGHT_CLIP(s->decorr[i].weightA, s->decorr[i].delta, s->decorr[i].samplesA[0], L); + L = L2; + R2 = R + ((s->decorr[i].weightB * L2 + 512) >> 10); + UPDATE_WEIGHT_CLIP(s->decorr[i].weightB, s->decorr[i].delta, L2, R); + R = R2; + s->decorr[i].samplesA[0] = R; + }else{ + R2 = R + ((s->decorr[i].weightB * s->decorr[i].samplesB[0] + 512) >> 10); + UPDATE_WEIGHT_CLIP(s->decorr[i].weightB, s->decorr[i].delta, s->decorr[i].samplesB[0], R); + R = R2; + + if(t == -3){ + R2 = s->decorr[i].samplesA[0]; + s->decorr[i].samplesA[0] = R; + } + + L2 = L + ((s->decorr[i].weightA * R2 + 512) >> 10); + UPDATE_WEIGHT_CLIP(s->decorr[i].weightA, s->decorr[i].delta, R2, L); + L = L2; + s->decorr[i].samplesB[0] = L; + } + } + pos = (pos + 1) & 7; + if(s->joint) + L += (R -= (L >> 1)); + crc = (crc * 3 + L) * 3 + R; + bit = (L & s->and) | s->or; + *dst++ = ((L + bit) << s->shift) - bit; + bit = (R & s->and) | s->or; + *dst++ = ((R + bit) << s->shift) - bit; + count++; + }while(!last && count < s->samples); + + if(crc != s->CRC){ + av_log(s->avctx, AV_LOG_ERROR, "CRC error\n"); + return -1; + } + return count * 2; +} + +static int wv_unpack_mono(WavpackContext *s, GetBitContext *gb, int16_t *dst) +{ + int i, j, count = 0; + int last, t; + int A, S, T, bit; + int pos = 0; + uint32_t crc = 0xFFFFFFFF; + + s->one = s->zero = s->zeroes = 0; + do{ + T = wv_get_value(s, gb, s->median, &last); + S = 0; + if(last) break; + for(i = 0; i < s->terms; i++){ + t = s->decorr[i].value; + if(t > 8){ + if(t & 1) + A = 2 * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1]; + else + A = (3 * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1]) >> 1; + s->decorr[i].samplesA[1] = s->decorr[i].samplesA[0]; + j = 0; + }else{ + A = s->decorr[i].samplesA[pos]; + j = (pos + t) & 7; + } + S = T + ((s->decorr[i].weightA * A + 512) >> 10); + if(A && T) s->decorr[i].weightA -= ((((T ^ A) >> 30) & 2) - 1) * s->decorr[i].delta; + s->decorr[i].samplesA[j] = T = S; + } + pos = (pos + 1) & 7; + crc = crc * 3 + S; + bit = (S & s->and) | s->or; + *dst++ = ((S + bit) << s->shift) - bit; + count++; + }while(!last && count < s->samples); + + if(crc != s->CRC){ + av_log(s->avctx, AV_LOG_ERROR, "CRC error\n"); + return -1; + } + return count; +} + +static av_cold int wavpack_decode_init(AVCodecContext *avctx) +{ + WavpackContext *s = avctx->priv_data; + + s->avctx = avctx; + s->stereo = (avctx->channels == 2); + avctx->sample_fmt = SAMPLE_FMT_S16; + + return 0; +} + +static int wavpack_decode_frame(AVCodecContext *avctx, + void *data, int *data_size, + const uint8_t *buf, int buf_size) +{ + WavpackContext *s = avctx->priv_data; + int16_t *samples = data; + int samplecount; + int got_terms = 0, got_weights = 0, got_samples = 0, got_entropy = 0, got_bs = 0; + const uint8_t* buf_end = buf + buf_size; + int i, j, id, size, ssize, weights, t; + + if (buf_size == 0){ + *data_size = 0; + return 0; + } + + memset(s->decorr, 0, MAX_TERMS * sizeof(Decorr)); + memset(s->median, 0, sizeof(s->median)); + s->and = s->or = s->shift = 0; + + s->samples = AV_RL32(buf); buf += 4; + if(!s->samples){ + *data_size = 0; + return buf_size; + } + /* should not happen but who knows */ + if(s->samples * 2 * avctx->channels > *data_size){ + av_log(avctx, AV_LOG_ERROR, "Packet size is too big to be handled in lavc!\n"); + return -1; + } + s->stereo_in = (AV_RL32(buf) & WV_FALSE_STEREO) ? 0 : s->stereo; + s->joint = AV_RL32(buf) & WV_JOINT_STEREO; buf += 4; + s->CRC = AV_RL32(buf); buf += 4; + // parse metadata blocks + while(buf < buf_end){ + id = *buf++; + size = *buf++; + if(id & WP_IDF_LONG) { + size |= (*buf++) << 8; + size |= (*buf++) << 16; + } + size <<= 1; // size is specified in words + ssize = size; + if(id & WP_IDF_ODD) size--; + if(size < 0){ + av_log(avctx, AV_LOG_ERROR, "Got incorrect block %02X with size %i\n", id, size); + break; + } + if(buf + ssize > buf_end){ + av_log(avctx, AV_LOG_ERROR, "Block size %i is out of bounds\n", size); + break; + } + if(id & WP_IDF_IGNORE){ + buf += ssize; + continue; + } + switch(id & WP_IDF_MASK){ + case WP_ID_DECTERMS: + s->terms = size; + if(s->terms > MAX_TERMS){ + av_log(avctx, AV_LOG_ERROR, "Too many decorrelation terms\n"); + buf += ssize; + continue; + } + for(i = 0; i < s->terms; i++) { + s->decorr[s->terms - i - 1].value = (*buf & 0x1F) - 5; + s->decorr[s->terms - i - 1].delta = *buf >> 5; + buf++; + } + got_terms = 1; + break; + case WP_ID_DECWEIGHTS: + if(!got_terms){ + av_log(avctx, AV_LOG_ERROR, "No decorrelation terms met\n"); + continue; + } + weights = size >> s->stereo_in; + if(weights > MAX_TERMS || weights > s->terms){ + av_log(avctx, AV_LOG_ERROR, "Too many decorrelation weights\n"); + buf += ssize; + continue; + } + for(i = 0; i < weights; i++) { + t = (int8_t)(*buf++); + s->decorr[s->terms - i - 1].weightA = t << 3; + if(s->decorr[s->terms - i - 1].weightA > 0) + s->decorr[s->terms - i - 1].weightA += (s->decorr[s->terms - i - 1].weightA + 64) >> 7; + if(s->stereo_in){ + t = (int8_t)(*buf++); + s->decorr[s->terms - i - 1].weightB = t << 3; + if(s->decorr[s->terms - i - 1].weightB > 0) + s->decorr[s->terms - i - 1].weightB += (s->decorr[s->terms - i - 1].weightB + 64) >> 7; + } + } + got_weights = 1; + break; + case WP_ID_DECSAMPLES: + if(!got_terms){ + av_log(avctx, AV_LOG_ERROR, "No decorrelation terms met\n"); + continue; + } + t = 0; + for(i = s->terms - 1; (i >= 0) && (t < size); i--) { + if(s->decorr[i].value > 8){ + s->decorr[i].samplesA[0] = wp_exp2(AV_RL16(buf)); buf += 2; + s->decorr[i].samplesA[1] = wp_exp2(AV_RL16(buf)); buf += 2; + if(s->stereo_in){ + s->decorr[i].samplesB[0] = wp_exp2(AV_RL16(buf)); buf += 2; + s->decorr[i].samplesB[1] = wp_exp2(AV_RL16(buf)); buf += 2; + t += 4; + } + t += 4; + }else if(s->decorr[i].value < 0){ + s->decorr[i].samplesA[0] = wp_exp2(AV_RL16(buf)); buf += 2; + s->decorr[i].samplesB[0] = wp_exp2(AV_RL16(buf)); buf += 2; + t += 4; + }else{ + for(j = 0; j < s->decorr[i].value; j++){ + s->decorr[i].samplesA[j] = wp_exp2(AV_RL16(buf)); buf += 2; + if(s->stereo_in){ + s->decorr[i].samplesB[j] = wp_exp2(AV_RL16(buf)); buf += 2; + } + } + t += s->decorr[i].value * 2 * (s->stereo_in + 1); + } + } + got_samples = 1; + break; + case WP_ID_ENTROPY: + if(size != 6 * (s->stereo_in + 1)){ + av_log(avctx, AV_LOG_ERROR, "Entropy vars size should be %i, got %i", 6 * (s->stereo_in + 1), size); + buf += ssize; + continue; + } + for(i = 0; i < 3 * (s->stereo_in + 1); i++){ + s->median[i] = wp_exp2(AV_RL16(buf)); + buf += 2; + } + got_entropy = 1; + break; + case WP_ID_INT32INFO: + if(size != 4 || *buf){ + av_log(avctx, AV_LOG_ERROR, "Invalid INT32INFO, size = %i, sent_bits = %i\n", size, *buf); + buf += ssize; + continue; + } + if(buf[1]) + s->shift = buf[1]; + else if(buf[2]){ + s->and = s->or = 1; + s->shift = buf[2]; + }else if(buf[3]){ + s->and = 1; + s->shift = buf[3]; + } + buf += 4; + break; + case WP_ID_DATA: + init_get_bits(&s->gb, buf, size * 8); + s->data_size = size * 8; + buf += size; + got_bs = 1; + break; + default: + buf += size; + } + if(id & WP_IDF_ODD) buf++; + } + if(!got_terms){ + av_log(avctx, AV_LOG_ERROR, "No block with decorrelation terms\n"); + return -1; + } + if(!got_weights){ + av_log(avctx, AV_LOG_ERROR, "No block with decorrelation weights\n"); + return -1; + } + if(!got_samples){ + av_log(avctx, AV_LOG_ERROR, "No block with decorrelation samples\n"); + return -1; + } + if(!got_entropy){ + av_log(avctx, AV_LOG_ERROR, "No block with entropy info\n"); + return -1; + } + if(!got_bs){ + av_log(avctx, AV_LOG_ERROR, "Packed samples not found\n"); + return -1; + } + + if(s->stereo_in) + samplecount = wv_unpack_stereo(s, &s->gb, samples); + else{ + samplecount = wv_unpack_mono(s, &s->gb, samples); + if(s->stereo){ + int16_t *dst = samples + samplecount * 2; + int16_t *src = samples + samplecount; + int cnt = samplecount; + while(cnt--){ + *--dst = *--src; + *--dst = *src; + } + samplecount *= 2; + } + } + *data_size = samplecount * 2; + + return buf_size; +} + +AVCodec wavpack_decoder = { + "wavpack", + CODEC_TYPE_AUDIO, + CODEC_ID_WAVPACK, + sizeof(WavpackContext), + wavpack_decode_init, + NULL, + NULL, + wavpack_decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("WavPack"), +}; diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/wma.c b/src/add-ons/media/plugins/avcodec/libavcodec/wma.c new file mode 100644 index 0000000000..2bbb0994cc --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/wma.c @@ -0,0 +1,384 @@ +/* + * WMA compatible codec + * Copyright (c) 2002-2007 The FFmpeg Project. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "wma.h" +#include "wmadata.h" + +#undef NDEBUG +#include + +/* XXX: use same run/length optimization as mpeg decoders */ +//FIXME maybe split decode / encode or pass flag +static void init_coef_vlc(VLC *vlc, + uint16_t **prun_table, uint16_t **plevel_table, uint16_t **pint_table, + const CoefVLCTable *vlc_table) +{ + int n = vlc_table->n; + const uint8_t *table_bits = vlc_table->huffbits; + const uint32_t *table_codes = vlc_table->huffcodes; + const uint16_t *levels_table = vlc_table->levels; + uint16_t *run_table, *level_table, *int_table; + int i, l, j, k, level; + + init_vlc(vlc, VLCBITS, n, table_bits, 1, 1, table_codes, 4, 4, 0); + + run_table = av_malloc(n * sizeof(uint16_t)); + level_table = av_malloc(n * sizeof(uint16_t)); + int_table = av_malloc(n * sizeof(uint16_t)); + i = 2; + level = 1; + k = 0; + while (i < n) { + int_table[k]= i; + l = levels_table[k++]; + for(j=0;jpriv_data; + int i; + float bps1, high_freq; + volatile float bps; + int sample_rate1; + int coef_vlc_table; + + if( avctx->sample_rate<=0 || avctx->sample_rate>50000 + || avctx->channels<=0 || avctx->channels>8 + || avctx->bit_rate<=0) + return -1; + + s->sample_rate = avctx->sample_rate; + s->nb_channels = avctx->channels; + s->bit_rate = avctx->bit_rate; + s->block_align = avctx->block_align; + + dsputil_init(&s->dsp, avctx); + + if (avctx->codec->id == CODEC_ID_WMAV1) { + s->version = 1; + } else { + s->version = 2; + } + + /* compute MDCT block size */ + if (s->sample_rate <= 16000) { + s->frame_len_bits = 9; + } else if (s->sample_rate <= 22050 || + (s->sample_rate <= 32000 && s->version == 1)) { + s->frame_len_bits = 10; + } else { + s->frame_len_bits = 11; + } + s->frame_len = 1 << s->frame_len_bits; + if (s->use_variable_block_len) { + int nb_max, nb; + nb = ((flags2 >> 3) & 3) + 1; + if ((s->bit_rate / s->nb_channels) >= 32000) + nb += 2; + nb_max = s->frame_len_bits - BLOCK_MIN_BITS; + if (nb > nb_max) + nb = nb_max; + s->nb_block_sizes = nb + 1; + } else { + s->nb_block_sizes = 1; + } + + /* init rate dependent parameters */ + s->use_noise_coding = 1; + high_freq = s->sample_rate * 0.5; + + /* if version 2, then the rates are normalized */ + sample_rate1 = s->sample_rate; + if (s->version == 2) { + if (sample_rate1 >= 44100) + sample_rate1 = 44100; + else if (sample_rate1 >= 22050) + sample_rate1 = 22050; + else if (sample_rate1 >= 16000) + sample_rate1 = 16000; + else if (sample_rate1 >= 11025) + sample_rate1 = 11025; + else if (sample_rate1 >= 8000) + sample_rate1 = 8000; + } + + bps = (float)s->bit_rate / (float)(s->nb_channels * s->sample_rate); + s->byte_offset_bits = av_log2((int)(bps * s->frame_len / 8.0 + 0.5)) + 2; + + /* compute high frequency value and choose if noise coding should + be activated */ + bps1 = bps; + if (s->nb_channels == 2) + bps1 = bps * 1.6; + if (sample_rate1 == 44100) { + if (bps1 >= 0.61) + s->use_noise_coding = 0; + else + high_freq = high_freq * 0.4; + } else if (sample_rate1 == 22050) { + if (bps1 >= 1.16) + s->use_noise_coding = 0; + else if (bps1 >= 0.72) + high_freq = high_freq * 0.7; + else + high_freq = high_freq * 0.6; + } else if (sample_rate1 == 16000) { + if (bps > 0.5) + high_freq = high_freq * 0.5; + else + high_freq = high_freq * 0.3; + } else if (sample_rate1 == 11025) { + high_freq = high_freq * 0.7; + } else if (sample_rate1 == 8000) { + if (bps <= 0.625) { + high_freq = high_freq * 0.5; + } else if (bps > 0.75) { + s->use_noise_coding = 0; + } else { + high_freq = high_freq * 0.65; + } + } else { + if (bps >= 0.8) { + high_freq = high_freq * 0.75; + } else if (bps >= 0.6) { + high_freq = high_freq * 0.6; + } else { + high_freq = high_freq * 0.5; + } + } + dprintf(s->avctx, "flags2=0x%x\n", flags2); + dprintf(s->avctx, "version=%d channels=%d sample_rate=%d bitrate=%d block_align=%d\n", + s->version, s->nb_channels, s->sample_rate, s->bit_rate, + s->block_align); + dprintf(s->avctx, "bps=%f bps1=%f high_freq=%f bitoffset=%d\n", + bps, bps1, high_freq, s->byte_offset_bits); + dprintf(s->avctx, "use_noise_coding=%d use_exp_vlc=%d nb_block_sizes=%d\n", + s->use_noise_coding, s->use_exp_vlc, s->nb_block_sizes); + + /* compute the scale factor band sizes for each MDCT block size */ + { + int a, b, pos, lpos, k, block_len, i, j, n; + const uint8_t *table; + + if (s->version == 1) { + s->coefs_start = 3; + } else { + s->coefs_start = 0; + } + for(k = 0; k < s->nb_block_sizes; k++) { + block_len = s->frame_len >> k; + + if (s->version == 1) { + lpos = 0; + for(i=0;i<25;i++) { + a = wma_critical_freqs[i]; + b = s->sample_rate; + pos = ((block_len * 2 * a) + (b >> 1)) / b; + if (pos > block_len) + pos = block_len; + s->exponent_bands[0][i] = pos - lpos; + if (pos >= block_len) { + i++; + break; + } + lpos = pos; + } + s->exponent_sizes[0] = i; + } else { + /* hardcoded tables */ + table = NULL; + a = s->frame_len_bits - BLOCK_MIN_BITS - k; + if (a < 3) { + if (s->sample_rate >= 44100) + table = exponent_band_44100[a]; + else if (s->sample_rate >= 32000) + table = exponent_band_32000[a]; + else if (s->sample_rate >= 22050) + table = exponent_band_22050[a]; + } + if (table) { + n = *table++; + for(i=0;iexponent_bands[k][i] = table[i]; + s->exponent_sizes[k] = n; + } else { + j = 0; + lpos = 0; + for(i=0;i<25;i++) { + a = wma_critical_freqs[i]; + b = s->sample_rate; + pos = ((block_len * 2 * a) + (b << 1)) / (4 * b); + pos <<= 2; + if (pos > block_len) + pos = block_len; + if (pos > lpos) + s->exponent_bands[k][j++] = pos - lpos; + if (pos >= block_len) + break; + lpos = pos; + } + s->exponent_sizes[k] = j; + } + } + + /* max number of coefs */ + s->coefs_end[k] = (s->frame_len - ((s->frame_len * 9) / 100)) >> k; + /* high freq computation */ + s->high_band_start[k] = (int)((block_len * 2 * high_freq) / + s->sample_rate + 0.5); + n = s->exponent_sizes[k]; + j = 0; + pos = 0; + for(i=0;iexponent_bands[k][i]; + end = pos; + if (start < s->high_band_start[k]) + start = s->high_band_start[k]; + if (end > s->coefs_end[k]) + end = s->coefs_end[k]; + if (end > start) + s->exponent_high_bands[k][j++] = end - start; + } + s->exponent_high_sizes[k] = j; +#if 0 + tprintf(s->avctx, "%5d: coefs_end=%d high_band_start=%d nb_high_bands=%d: ", + s->frame_len >> k, + s->coefs_end[k], + s->high_band_start[k], + s->exponent_high_sizes[k]); + for(j=0;jexponent_high_sizes[k];j++) + tprintf(s->avctx, " %d", s->exponent_high_bands[k][j]); + tprintf(s->avctx, "\n"); +#endif + } + } + +#ifdef TRACE + { + int i, j; + for(i = 0; i < s->nb_block_sizes; i++) { + tprintf(s->avctx, "%5d: n=%2d:", + s->frame_len >> i, + s->exponent_sizes[i]); + for(j=0;jexponent_sizes[i];j++) + tprintf(s->avctx, " %d", s->exponent_bands[i][j]); + tprintf(s->avctx, "\n"); + } + } +#endif + + /* init MDCT windows : simple sinus window */ + for(i = 0; i < s->nb_block_sizes; i++) { + int n; + n = 1 << (s->frame_len_bits - i); + ff_sine_window_init(ff_sine_windows[s->frame_len_bits - i - 7], n); + s->windows[i] = ff_sine_windows[s->frame_len_bits - i - 7]; + } + + s->reset_block_lengths = 1; + + if (s->use_noise_coding) { + + /* init the noise generator */ + if (s->use_exp_vlc) + s->noise_mult = 0.02; + else + s->noise_mult = 0.04; + +#ifdef TRACE + for(i=0;inoise_table[i] = 1.0 * s->noise_mult; +#else + { + unsigned int seed; + float norm; + seed = 1; + norm = (1.0 / (float)(1LL << 31)) * sqrt(3) * s->noise_mult; + for(i=0;inoise_table[i] = (float)((int)seed) * norm; + } + } +#endif + } + + /* choose the VLC tables for the coefficients */ + coef_vlc_table = 2; + if (s->sample_rate >= 32000) { + if (bps1 < 0.72) + coef_vlc_table = 0; + else if (bps1 < 1.16) + coef_vlc_table = 1; + } + s->coef_vlcs[0]= &coef_vlcs[coef_vlc_table * 2 ]; + s->coef_vlcs[1]= &coef_vlcs[coef_vlc_table * 2 + 1]; + init_coef_vlc(&s->coef_vlc[0], &s->run_table[0], &s->level_table[0], &s->int_table[0], + s->coef_vlcs[0]); + init_coef_vlc(&s->coef_vlc[1], &s->run_table[1], &s->level_table[1], &s->int_table[1], + s->coef_vlcs[1]); + + return 0; +} + +int ff_wma_total_gain_to_bits(int total_gain){ + if (total_gain < 15) return 13; + else if (total_gain < 32) return 12; + else if (total_gain < 40) return 11; + else if (total_gain < 45) return 10; + else return 9; +} + +int ff_wma_end(AVCodecContext *avctx) +{ + WMACodecContext *s = avctx->priv_data; + int i; + + for(i = 0; i < s->nb_block_sizes; i++) + ff_mdct_end(&s->mdct_ctx[i]); + + if (s->use_exp_vlc) { + free_vlc(&s->exp_vlc); + } + if (s->use_noise_coding) { + free_vlc(&s->hgain_vlc); + } + for(i = 0;i < 2; i++) { + free_vlc(&s->coef_vlc[i]); + av_free(s->run_table[i]); + av_free(s->level_table[i]); + av_free(s->int_table[i]); + } + + return 0; +} diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/wma.h b/src/add-ons/media/plugins/avcodec/libavcodec/wma.h new file mode 100644 index 0000000000..43b5d0c339 --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/wma.h @@ -0,0 +1,149 @@ +/* + * WMA compatible codec + * Copyright (c) 2002-2007 The FFmpeg Project. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FFMPEG_WMA_H +#define FFMPEG_WMA_H + +#include "bitstream.h" +#include "dsputil.h" + +/* size of blocks */ +#define BLOCK_MIN_BITS 7 +#define BLOCK_MAX_BITS 11 +#define BLOCK_MAX_SIZE (1 << BLOCK_MAX_BITS) + +#define BLOCK_NB_SIZES (BLOCK_MAX_BITS - BLOCK_MIN_BITS + 1) + +/* XXX: find exact max size */ +#define HIGH_BAND_MAX_SIZE 16 + +#define NB_LSP_COEFS 10 + +/* XXX: is it a suitable value ? */ +#define MAX_CODED_SUPERFRAME_SIZE 16384 + +#define MAX_CHANNELS 2 + +#define NOISE_TAB_SIZE 8192 + +#define LSP_POW_BITS 7 + +//FIXME should be in wmadec +#define VLCBITS 9 +#define VLCMAX ((22+VLCBITS-1)/VLCBITS) + +typedef struct CoefVLCTable { + int n; ///< total number of codes + int max_level; + const uint32_t *huffcodes; ///< VLC bit values + const uint8_t *huffbits; ///< VLC bit size + const uint16_t *levels; ///< table to build run/level tables +} CoefVLCTable; + +typedef struct WMACodecContext { + AVCodecContext* avctx; + GetBitContext gb; + PutBitContext pb; + int sample_rate; + int nb_channels; + int bit_rate; + int version; ///< 1 = 0x160 (WMAV1), 2 = 0x161 (WMAV2) + int block_align; + int use_bit_reservoir; + int use_variable_block_len; + int use_exp_vlc; ///< exponent coding: 0 = lsp, 1 = vlc + delta + int use_noise_coding; ///< true if perceptual noise is added + int byte_offset_bits; + VLC exp_vlc; + int exponent_sizes[BLOCK_NB_SIZES]; + uint16_t exponent_bands[BLOCK_NB_SIZES][25]; + int high_band_start[BLOCK_NB_SIZES]; ///< index of first coef in high band + int coefs_start; ///< first coded coef + int coefs_end[BLOCK_NB_SIZES]; ///< max number of coded coefficients + int exponent_high_sizes[BLOCK_NB_SIZES]; + int exponent_high_bands[BLOCK_NB_SIZES][HIGH_BAND_MAX_SIZE]; + VLC hgain_vlc; + + /* coded values in high bands */ + int high_band_coded[MAX_CHANNELS][HIGH_BAND_MAX_SIZE]; + int high_band_values[MAX_CHANNELS][HIGH_BAND_MAX_SIZE]; + + /* there are two possible tables for spectral coefficients */ +//FIXME the following 3 tables should be shared between decoders + VLC coef_vlc[2]; + uint16_t *run_table[2]; + uint16_t *level_table[2]; + uint16_t *int_table[2]; + const CoefVLCTable *coef_vlcs[2]; + /* frame info */ + int frame_len; ///< frame length in samples + int frame_len_bits; ///< frame_len = 1 << frame_len_bits + int nb_block_sizes; ///< number of block sizes + /* block info */ + int reset_block_lengths; + int block_len_bits; ///< log2 of current block length + int next_block_len_bits; ///< log2 of next block length + int prev_block_len_bits; ///< log2 of prev block length + int block_len; ///< block length in samples + int block_num; ///< block number in current frame + int block_pos; ///< current position in frame + uint8_t ms_stereo; ///< true if mid/side stereo mode + uint8_t channel_coded[MAX_CHANNELS]; ///< true if channel is coded + int exponents_bsize[MAX_CHANNELS]; ///< log2 ratio frame/exp. length + DECLARE_ALIGNED_16(float, exponents[MAX_CHANNELS][BLOCK_MAX_SIZE]); + float max_exponent[MAX_CHANNELS]; + int16_t coefs1[MAX_CHANNELS][BLOCK_MAX_SIZE]; + DECLARE_ALIGNED_16(float, coefs[MAX_CHANNELS][BLOCK_MAX_SIZE]); + DECLARE_ALIGNED_16(FFTSample, output[BLOCK_MAX_SIZE * 2]); + MDCTContext mdct_ctx[BLOCK_NB_SIZES]; + float *windows[BLOCK_NB_SIZES]; + /* output buffer for one frame and the last for IMDCT windowing */ + DECLARE_ALIGNED_16(float, frame_out[MAX_CHANNELS][BLOCK_MAX_SIZE * 2]); + /* last frame info */ + uint8_t last_superframe[MAX_CODED_SUPERFRAME_SIZE + 4]; /* padding added */ + int last_bitoffset; + int last_superframe_len; + float noise_table[NOISE_TAB_SIZE]; + int noise_index; + float noise_mult; /* XXX: suppress that and integrate it in the noise array */ + /* lsp_to_curve tables */ + float lsp_cos_table[BLOCK_MAX_SIZE]; + float lsp_pow_e_table[256]; + float lsp_pow_m_table1[(1 << LSP_POW_BITS)]; + float lsp_pow_m_table2[(1 << LSP_POW_BITS)]; + DSPContext dsp; + +#ifdef TRACE + int frame_count; +#endif +} WMACodecContext; + +extern const uint16_t ff_wma_hgain_huffcodes[37]; +extern const uint8_t ff_wma_hgain_huffbits[37]; +extern const float ff_wma_lsp_codebook[NB_LSP_COEFS][16]; +extern const uint32_t ff_wma_scale_huffcodes[121]; +extern const uint8_t ff_wma_scale_huffbits[121]; + +int ff_wma_init(AVCodecContext * avctx, int flags2); +int ff_wma_total_gain_to_bits(int total_gain); +int ff_wma_end(AVCodecContext *avctx); + +#endif /* FFMPEG_WMA_H */ diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/wmadata.h b/src/add-ons/media/plugins/avcodec/libavcodec/wmadata.h index ee17207102..aa2a120a2b 100644 --- a/src/add-ons/media/plugins/avcodec/libavcodec/wmadata.h +++ b/src/add-ons/media/plugins/avcodec/libavcodec/wmadata.h @@ -1,8 +1,35 @@ +/* + * WMA compatible decoder + * copyright (c) 2002 The FFmpeg Project + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + /** * @file wmadata.h * Various WMA tables. */ +#ifndef FFMPEG_WMADATA_H +#define FFMPEG_WMADATA_H + +#include +#include "wma.h" + static const uint16_t wma_critical_freqs[25] = { 100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270, 1480, 1720, 2000, 2320, 2700, 3150, @@ -29,7 +56,7 @@ static const uint8_t exponent_band_44100[3][25] = { { 17, 4, 8, 8, 4, 12, 12, 8, 8, 24, 16, 20, 24, 32, 40, 60, 80, 152, }, }; -static const uint16_t hgain_huffcodes[37] = { +const uint16_t ff_wma_hgain_huffcodes[37] = { 0x00003, 0x002e7, 0x00001, 0x005cd, 0x0005d, 0x005c9, 0x0005e, 0x00003, 0x00016, 0x0000b, 0x00001, 0x00006, 0x00001, 0x00006, 0x00004, 0x00005, 0x00004, 0x00007, 0x00003, 0x00007, 0x00004, 0x0000a, 0x0000a, 0x00002, @@ -37,7 +64,7 @@ static const uint16_t hgain_huffcodes[37] = { 0x005c8, 0x000b8, 0x005ca, 0x005cb, 0x005cc, }; -static const uint8_t hgain_huffbits[37] = { +const uint8_t ff_wma_hgain_huffbits[37] = { 10, 12, 10, 13, 9, 13, 9, 8, 7, 5, 5, 4, 4, 3, 3, 3, 4, 3, 4, 4, 5, 5, 6, 8, @@ -45,7 +72,7 @@ static const uint8_t hgain_huffbits[37] = { 13, 10, 13, 13, 13, }; -static const float lsp_codebook[NB_LSP_COEFS][16] = { +const float ff_wma_lsp_codebook[NB_LSP_COEFS][16] = { { 1.98732877, 1.97944528, 1.97179088, 1.96260549, 1.95038374, 1.93336114, 1.90719232, 1.86191415, }, { 1.97260000, 1.96083160, 1.94982586, 1.93806164, 1.92516608, 1.91010199, 1.89232331, 1.87149812, 1.84564818, 1.81358067, 1.77620070, 1.73265264, 1.67907855, 1.60959081, 1.50829650, 1.33120330, }, @@ -65,7 +92,7 @@ static const float lsp_codebook[NB_LSP_COEFS][16] = { { -1.56144989, -1.65944032, -1.72689685, -1.77857740, -1.82203011, -1.86220079, -1.90283983, -1.94820479, }, }; -static const uint32_t scale_huffcodes[121] = { +const uint32_t ff_wma_scale_huffcodes[121] = { 0x3ffe8, 0x3ffe6, 0x3ffe7, 0x3ffe5, 0x7fff5, 0x7fff1, 0x7ffed, 0x7fff6, 0x7ffee, 0x7ffef, 0x7fff0, 0x7fffc, 0x7fffd, 0x7ffff, 0x7fffe, 0x7fff7, 0x7fff8, 0x7fffb, 0x7fff9, 0x3ffe4, 0x7fffa, 0x3ffe3, 0x1ffef, 0x1fff0, @@ -84,7 +111,7 @@ static const uint32_t scale_huffcodes[121] = { 0x7fff3, }; -static const uint8_t scale_huffbits[121] = { +const uint8_t ff_wma_scale_huffbits[121] = { 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 18, 19, 18, 17, 17, @@ -1389,24 +1416,26 @@ static const uint16_t levels5[40] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; - + static const CoefVLCTable coef_vlcs[6] = { - { - sizeof(coef0_huffbits), coef0_huffcodes, coef0_huffbits, levels0, + { + sizeof(coef0_huffbits), sizeof(levels0)/2, coef0_huffcodes, coef0_huffbits, levels0, }, - { - sizeof(coef1_huffbits), coef1_huffcodes, coef1_huffbits, levels1, + { + sizeof(coef1_huffbits), sizeof(levels1)/2, coef1_huffcodes, coef1_huffbits, levels1, }, - { - sizeof(coef2_huffbits), coef2_huffcodes, coef2_huffbits, levels2, + { + sizeof(coef2_huffbits), sizeof(levels2)/2, coef2_huffcodes, coef2_huffbits, levels2, }, - { - sizeof(coef3_huffbits), coef3_huffcodes, coef3_huffbits, levels3, + { + sizeof(coef3_huffbits), sizeof(levels3)/2, coef3_huffcodes, coef3_huffbits, levels3, }, - { - sizeof(coef4_huffbits), coef4_huffcodes, coef4_huffbits, levels4, + { + sizeof(coef4_huffbits), sizeof(levels4)/2, coef4_huffcodes, coef4_huffbits, levels4, }, - { - sizeof(coef5_huffbits), coef5_huffcodes, coef5_huffbits, levels5, + { + sizeof(coef5_huffbits), sizeof(levels5)/2, coef5_huffcodes, coef5_huffbits, levels5, }, }; + +#endif /* FFMPEG_WMADATA_H */ diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/wmadec.c b/src/add-ons/media/plugins/avcodec/libavcodec/wmadec.c index 25498c4d28..74b95cd528 100644 --- a/src/add-ons/media/plugins/avcodec/libavcodec/wmadec.c +++ b/src/add-ons/media/plugins/avcodec/libavcodec/wmadec.c @@ -2,546 +2,141 @@ * WMA compatible decoder * Copyright (c) 2002 The FFmpeg Project. * - * This library is free software; you can redistribute it and/or + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * @file wmadec.c * WMA compatible decoder. + * This decoder handles Microsoft Windows Media Audio data, versions 1 & 2. + * WMA v1 is identified by audio format 0x160 in Microsoft media files + * (ASF/AVI/WAV). WMA v2 is identified by audio format 0x161. + * + * To use this decoder, a calling application must supply the extra data + * bytes provided with the WMA data. These are the extra, codec-specific + * bytes at the end of a WAVEFORMATEX data structure. Transmit these bytes + * to the decoder using the extradata[_size] fields in AVCodecContext. There + * should be 4 extra bytes for v1 data and 6 extra bytes for v2 data. */ #include "avcodec.h" -#include "dsputil.h" +#include "wma.h" -/* size of blocks */ -#define BLOCK_MIN_BITS 7 -#define BLOCK_MAX_BITS 11 -#define BLOCK_MAX_SIZE (1 << BLOCK_MAX_BITS) +#undef NDEBUG +#include -#define BLOCK_NB_SIZES (BLOCK_MAX_BITS - BLOCK_MIN_BITS + 1) +#define EXPVLCBITS 8 +#define EXPMAX ((19+EXPVLCBITS-1)/EXPVLCBITS) -/* XXX: find exact max size */ -#define HIGH_BAND_MAX_SIZE 16 +#define HGAINVLCBITS 9 +#define HGAINMAX ((13+HGAINVLCBITS-1)/HGAINVLCBITS) -#define NB_LSP_COEFS 10 - -/* XXX: is it a suitable value ? */ -#define MAX_CODED_SUPERFRAME_SIZE 4096 - -#define MAX_CHANNELS 2 - -#define NOISE_TAB_SIZE 8192 - -#define LSP_POW_BITS 7 - -typedef struct WMADecodeContext { - GetBitContext gb; - int sample_rate; - int nb_channels; - int bit_rate; - int version; /* 1 = 0x160 (WMAV1), 2 = 0x161 (WMAV2) */ - int block_align; - int use_bit_reservoir; - int use_variable_block_len; - int use_exp_vlc; /* exponent coding: 0 = lsp, 1 = vlc + delta */ - int use_noise_coding; /* true if perceptual noise is added */ - int byte_offset_bits; - VLC exp_vlc; - int exponent_sizes[BLOCK_NB_SIZES]; - uint16_t exponent_bands[BLOCK_NB_SIZES][25]; - int high_band_start[BLOCK_NB_SIZES]; /* index of first coef in high band */ - int coefs_start; /* first coded coef */ - int coefs_end[BLOCK_NB_SIZES]; /* max number of coded coefficients */ - int exponent_high_sizes[BLOCK_NB_SIZES]; - int exponent_high_bands[BLOCK_NB_SIZES][HIGH_BAND_MAX_SIZE]; - VLC hgain_vlc; - - /* coded values in high bands */ - int high_band_coded[MAX_CHANNELS][HIGH_BAND_MAX_SIZE]; - int high_band_values[MAX_CHANNELS][HIGH_BAND_MAX_SIZE]; - - /* there are two possible tables for spectral coefficients */ - VLC coef_vlc[2]; - uint16_t *run_table[2]; - uint16_t *level_table[2]; - /* frame info */ - int frame_len; /* frame length in samples */ - int frame_len_bits; /* frame_len = 1 << frame_len_bits */ - int nb_block_sizes; /* number of block sizes */ - /* block info */ - int reset_block_lengths; - int block_len_bits; /* log2 of current block length */ - int next_block_len_bits; /* log2 of next block length */ - int prev_block_len_bits; /* log2 of prev block length */ - int block_len; /* block length in samples */ - int block_num; /* block number in current frame */ - int block_pos; /* current position in frame */ - uint8_t ms_stereo; /* true if mid/side stereo mode */ - uint8_t channel_coded[MAX_CHANNELS]; /* true if channel is coded */ - float exponents[MAX_CHANNELS][BLOCK_MAX_SIZE] __attribute__((aligned(16))); - float max_exponent[MAX_CHANNELS]; - int16_t coefs1[MAX_CHANNELS][BLOCK_MAX_SIZE]; - float coefs[MAX_CHANNELS][BLOCK_MAX_SIZE] __attribute__((aligned(16))); - MDCTContext mdct_ctx[BLOCK_NB_SIZES]; - float *windows[BLOCK_NB_SIZES]; - FFTSample mdct_tmp[BLOCK_MAX_SIZE] __attribute__((aligned(16))); /* temporary storage for imdct */ - /* output buffer for one frame and the last for IMDCT windowing */ - float frame_out[MAX_CHANNELS][BLOCK_MAX_SIZE * 2] __attribute__((aligned(16))); - /* last frame info */ - uint8_t last_superframe[MAX_CODED_SUPERFRAME_SIZE + 4]; /* padding added */ - int last_bitoffset; - int last_superframe_len; - float noise_table[NOISE_TAB_SIZE]; - int noise_index; - float noise_mult; /* XXX: suppress that and integrate it in the noise array */ - /* lsp_to_curve tables */ - float lsp_cos_table[BLOCK_MAX_SIZE]; - float lsp_pow_e_table[256]; - float lsp_pow_m_table1[(1 << LSP_POW_BITS)]; - float lsp_pow_m_table2[(1 << LSP_POW_BITS)]; +static void wma_lsp_to_curve_init(WMACodecContext *s, int frame_len); #ifdef TRACE - int frame_count; -#endif -} WMADecodeContext; - -typedef struct CoefVLCTable { - int n; /* total number of codes */ - const uint32_t *huffcodes; /* VLC bit values */ - const uint8_t *huffbits; /* VLC bit size */ - const uint16_t *levels; /* table to build run/level tables */ -} CoefVLCTable; - -static void wma_lsp_to_curve_init(WMADecodeContext *s, int frame_len); - -#include "wmadata.h" - -#ifdef TRACE -static void dump_shorts(const char *name, const short *tab, int n) +static void dump_shorts(WMACodecContext *s, const char *name, const short *tab, int n) { int i; - tprintf("%s[%d]:\n", name, n); + tprintf(s->avctx, "%s[%d]:\n", name, n); for(i=0;iavctx, "%4d: ", i); + tprintf(s->avctx, " %5d.0", tab[i]); if ((i & 7) == 7) - tprintf("\n"); + tprintf(s->avctx, "\n"); } } -static void dump_floats(const char *name, int prec, const float *tab, int n) +static void dump_floats(WMACodecContext *s, const char *name, int prec, const float *tab, int n) { int i; - tprintf("%s[%d]:\n", name, n); + tprintf(s->avctx, "%s[%d]:\n", name, n); for(i=0;iavctx, "%4d: ", i); + tprintf(s->avctx, " %8.*f", prec, tab[i]); if ((i & 7) == 7) - tprintf("\n"); + tprintf(s->avctx, "\n"); } if ((i & 7) != 0) - tprintf("\n"); + tprintf(s->avctx, "\n"); } #endif -/* XXX: use same run/length optimization as mpeg decoders */ -static void init_coef_vlc(VLC *vlc, - uint16_t **prun_table, uint16_t **plevel_table, - const CoefVLCTable *vlc_table) -{ - int n = vlc_table->n; - const uint8_t *table_bits = vlc_table->huffbits; - const uint32_t *table_codes = vlc_table->huffcodes; - const uint16_t *levels_table = vlc_table->levels; - uint16_t *run_table, *level_table; - const uint16_t *p; - int i, l, j, level; - - init_vlc(vlc, 9, n, table_bits, 1, 1, table_codes, 4, 4); - - run_table = av_malloc(n * sizeof(uint16_t)); - level_table = av_malloc(n * sizeof(uint16_t)); - p = levels_table; - i = 2; - level = 1; - while (i < n) { - l = *p++; - for(j=0;jpriv_data; + WMACodecContext *s = avctx->priv_data; int i, flags1, flags2; - float *window; uint8_t *extradata; - float bps1, high_freq, bps; - int sample_rate1; - int coef_vlc_table; - - s->sample_rate = avctx->sample_rate; - s->nb_channels = avctx->channels; - s->bit_rate = avctx->bit_rate; - s->block_align = avctx->block_align; - if (avctx->codec->id == CODEC_ID_WMAV1) { - s->version = 1; - } else { - s->version = 2; - } - + s->avctx = avctx; + /* extract flag infos */ flags1 = 0; flags2 = 0; extradata = avctx->extradata; - if (s->version == 1 && avctx->extradata_size >= 4) { - flags1 = extradata[0] | (extradata[1] << 8); - flags2 = extradata[2] | (extradata[3] << 8); - } else if (s->version == 2 && avctx->extradata_size >= 6) { - flags1 = extradata[0] | (extradata[1] << 8) | - (extradata[2] << 16) | (extradata[3] << 24); - flags2 = extradata[4] | (extradata[5] << 8); + if (avctx->codec->id == CODEC_ID_WMAV1 && avctx->extradata_size >= 4) { + flags1 = AV_RL16(extradata); + flags2 = AV_RL16(extradata+2); + } else if (avctx->codec->id == CODEC_ID_WMAV2 && avctx->extradata_size >= 6) { + flags1 = AV_RL32(extradata); + flags2 = AV_RL16(extradata+4); } +// for(i=0; iextradata_size; i++) +// av_log(NULL, AV_LOG_ERROR, "%02X ", extradata[i]); + s->use_exp_vlc = flags2 & 0x0001; s->use_bit_reservoir = flags2 & 0x0002; s->use_variable_block_len = flags2 & 0x0004; - /* compute MDCT block size */ - if (s->sample_rate <= 16000) { - s->frame_len_bits = 9; - } else if (s->sample_rate <= 22050 || - (s->sample_rate <= 32000 && s->version == 1)) { - s->frame_len_bits = 10; - } else { - s->frame_len_bits = 11; - } - s->frame_len = 1 << s->frame_len_bits; - if (s->use_variable_block_len) { - int nb_max, nb; - nb = ((flags2 >> 3) & 3) + 1; - if ((s->bit_rate / s->nb_channels) >= 32000) - nb += 2; - nb_max = s->frame_len_bits - BLOCK_MIN_BITS; - if (nb > nb_max) - nb = nb_max; - s->nb_block_sizes = nb + 1; - } else { - s->nb_block_sizes = 1; - } - - /* init rate dependant parameters */ - s->use_noise_coding = 1; - high_freq = s->sample_rate * 0.5; - - /* if version 2, then the rates are normalized */ - sample_rate1 = s->sample_rate; - if (s->version == 2) { - if (sample_rate1 >= 44100) - sample_rate1 = 44100; - else if (sample_rate1 >= 22050) - sample_rate1 = 22050; - else if (sample_rate1 >= 16000) - sample_rate1 = 16000; - else if (sample_rate1 >= 11025) - sample_rate1 = 11025; - else if (sample_rate1 >= 8000) - sample_rate1 = 8000; - } - - bps = (float)s->bit_rate / (float)(s->nb_channels * s->sample_rate); - s->byte_offset_bits = av_log2((int)(bps * s->frame_len / 8.0)) + 2; - - /* compute high frequency value and choose if noise coding should - be activated */ - bps1 = bps; - if (s->nb_channels == 2) - bps1 = bps * 1.6; - if (sample_rate1 == 44100) { - if (bps1 >= 0.61) - s->use_noise_coding = 0; - else - high_freq = high_freq * 0.4; - } else if (sample_rate1 == 22050) { - if (bps1 >= 1.16) - s->use_noise_coding = 0; - else if (bps1 >= 0.72) - high_freq = high_freq * 0.7; - else - high_freq = high_freq * 0.6; - } else if (sample_rate1 == 16000) { - if (bps > 0.5) - high_freq = high_freq * 0.5; - else - high_freq = high_freq * 0.3; - } else if (sample_rate1 == 11025) { - high_freq = high_freq * 0.7; - } else if (sample_rate1 == 8000) { - if (bps <= 0.625) { - high_freq = high_freq * 0.5; - } else if (bps > 0.75) { - s->use_noise_coding = 0; - } else { - high_freq = high_freq * 0.65; - } - } else { - if (bps >= 0.8) { - high_freq = high_freq * 0.75; - } else if (bps >= 0.6) { - high_freq = high_freq * 0.6; - } else { - high_freq = high_freq * 0.5; - } - } - dprintf("flags1=0x%x flags2=0x%x\n", flags1, flags2); - dprintf("version=%d channels=%d sample_rate=%d bitrate=%d block_align=%d\n", - s->version, s->nb_channels, s->sample_rate, s->bit_rate, - s->block_align); - dprintf("bps=%f bps1=%f high_freq=%f bitoffset=%d\n", - bps, bps1, high_freq, s->byte_offset_bits); - dprintf("use_noise_coding=%d use_exp_vlc=%d nb_block_sizes=%d\n", - s->use_noise_coding, s->use_exp_vlc, s->nb_block_sizes); - - /* compute the scale factor band sizes for each MDCT block size */ - { - int a, b, pos, lpos, k, block_len, i, j, n; - const uint8_t *table; - - if (s->version == 1) { - s->coefs_start = 3; - } else { - s->coefs_start = 0; - } - for(k = 0; k < s->nb_block_sizes; k++) { - block_len = s->frame_len >> k; - - if (s->version == 1) { - lpos = 0; - for(i=0;i<25;i++) { - a = wma_critical_freqs[i]; - b = s->sample_rate; - pos = ((block_len * 2 * a) + (b >> 1)) / b; - if (pos > block_len) - pos = block_len; - s->exponent_bands[0][i] = pos - lpos; - if (pos >= block_len) { - i++; - break; - } - lpos = pos; - } - s->exponent_sizes[0] = i; - } else { - /* hardcoded tables */ - table = NULL; - a = s->frame_len_bits - BLOCK_MIN_BITS - k; - if (a < 3) { - if (s->sample_rate >= 44100) - table = exponent_band_44100[a]; - else if (s->sample_rate >= 32000) - table = exponent_band_32000[a]; - else if (s->sample_rate >= 22050) - table = exponent_band_22050[a]; - } - if (table) { - n = *table++; - for(i=0;iexponent_bands[k][i] = table[i]; - s->exponent_sizes[k] = n; - } else { - j = 0; - lpos = 0; - for(i=0;i<25;i++) { - a = wma_critical_freqs[i]; - b = s->sample_rate; - pos = ((block_len * 2 * a) + (b << 1)) / (4 * b); - pos <<= 2; - if (pos > block_len) - pos = block_len; - if (pos > lpos) - s->exponent_bands[k][j++] = pos - lpos; - if (pos >= block_len) - break; - lpos = pos; - } - s->exponent_sizes[k] = j; - } - } - - /* max number of coefs */ - s->coefs_end[k] = (s->frame_len - ((s->frame_len * 9) / 100)) >> k; - /* high freq computation */ - s->high_band_start[k] = (int)((block_len * 2 * high_freq) / - s->sample_rate + 0.5); - n = s->exponent_sizes[k]; - j = 0; - pos = 0; - for(i=0;iexponent_bands[k][i]; - end = pos; - if (start < s->high_band_start[k]) - start = s->high_band_start[k]; - if (end > s->coefs_end[k]) - end = s->coefs_end[k]; - if (end > start) - s->exponent_high_bands[k][j++] = end - start; - } - s->exponent_high_sizes[k] = j; -#if 0 - tprintf("%5d: coefs_end=%d high_band_start=%d nb_high_bands=%d: ", - s->frame_len >> k, - s->coefs_end[k], - s->high_band_start[k], - s->exponent_high_sizes[k]); - for(j=0;jexponent_high_sizes[k];j++) - tprintf(" %d", s->exponent_high_bands[k][j]); - tprintf("\n"); -#endif - } - } - -#ifdef TRACE - { - int i, j; - for(i = 0; i < s->nb_block_sizes; i++) { - tprintf("%5d: n=%2d:", - s->frame_len >> i, - s->exponent_sizes[i]); - for(j=0;jexponent_sizes[i];j++) - tprintf(" %d", s->exponent_bands[i][j]); - tprintf("\n"); - } - } -#endif + if(ff_wma_init(avctx, flags2)<0) + return -1; /* init MDCT */ for(i = 0; i < s->nb_block_sizes; i++) ff_mdct_init(&s->mdct_ctx[i], s->frame_len_bits - i + 1, 1); - - /* init MDCT windows : simple sinus window */ - for(i = 0; i < s->nb_block_sizes; i++) { - int n, j; - float alpha; - n = 1 << (s->frame_len_bits - i); - window = av_malloc(sizeof(float) * n); - alpha = M_PI / (2.0 * n); - for(j=0;jwindows[i] = window; - } - s->reset_block_lengths = 1; - if (s->use_noise_coding) { - - /* init the noise generator */ - if (s->use_exp_vlc) - s->noise_mult = 0.02; - else - s->noise_mult = 0.04; - -#ifdef TRACE - for(i=0;inoise_table[i] = 1.0 * s->noise_mult; -#else - { - unsigned int seed; - float norm; - seed = 1; - norm = (1.0 / (float)(1LL << 31)) * sqrt(3) * s->noise_mult; - for(i=0;inoise_table[i] = (float)((int)seed) * norm; - } - } -#endif - init_vlc(&s->hgain_vlc, 9, sizeof(hgain_huffbits), - hgain_huffbits, 1, 1, - hgain_huffcodes, 2, 2); + init_vlc(&s->hgain_vlc, HGAINVLCBITS, sizeof(ff_wma_hgain_huffbits), + ff_wma_hgain_huffbits, 1, 1, + ff_wma_hgain_huffcodes, 2, 2, 0); } if (s->use_exp_vlc) { - init_vlc(&s->exp_vlc, 9, sizeof(scale_huffbits), - scale_huffbits, 1, 1, - scale_huffcodes, 4, 4); + init_vlc(&s->exp_vlc, EXPVLCBITS, sizeof(ff_wma_scale_huffbits), //FIXME move out of context + ff_wma_scale_huffbits, 1, 1, + ff_wma_scale_huffcodes, 4, 4, 0); } else { wma_lsp_to_curve_init(s, s->frame_len); } - /* choose the VLC tables for the coefficients */ - coef_vlc_table = 2; - if (s->sample_rate >= 32000) { - if (bps1 < 0.72) - coef_vlc_table = 0; - else if (bps1 < 1.16) - coef_vlc_table = 1; - } - - init_coef_vlc(&s->coef_vlc[0], &s->run_table[0], &s->level_table[0], - &coef_vlcs[coef_vlc_table * 2]); - init_coef_vlc(&s->coef_vlc[1], &s->run_table[1], &s->level_table[1], - &coef_vlcs[coef_vlc_table * 2 + 1]); + avctx->sample_fmt = SAMPLE_FMT_S16; return 0; } -/* interpolate values for a bigger or smaller block. The block must - have multiple sizes */ -static void interpolate_array(float *scale, int old_size, int new_size) -{ - int i, j, jincr, k; - float v; - - if (new_size > old_size) { - jincr = new_size / old_size; - j = new_size; - for(i = old_size - 1; i >=0; i--) { - v = scale[i]; - k = jincr; - do { - scale[--j] = v; - } while (--k); - } - } else if (new_size < old_size) { - j = 0; - jincr = old_size / new_size; - for(i = 0; i < new_size; i++) { - scale[i] = scale[j]; - j += jincr; - } - } -} - -/* compute x^-0.25 with an exponent and mantissa table. We use linear - interpolation to reduce the mantissa table size at a small speed - expense (linear interpolation approximately doubles the number of - bits of precision). */ -static inline float pow_m1_4(WMADecodeContext *s, float x) +/** + * compute x^-0.25 with an exponent and mantissa table. We use linear + * interpolation to reduce the mantissa table size at a small speed + * expense (linear interpolation approximately doubles the number of + * bits of precision). + */ +static inline float pow_m1_4(WMACodecContext *s, float x) { union { float f; @@ -560,8 +155,8 @@ static inline float pow_m1_4(WMADecodeContext *s, float x) return s->lsp_pow_e_table[e] * (a + b * t.f); } -static void wma_lsp_to_curve_init(WMADecodeContext *s, int frame_len) -{ +static void wma_lsp_to_curve_init(WMACodecContext *s, int frame_len) +{ float wdel, a, b; int i, e, m; @@ -597,10 +192,12 @@ static void wma_lsp_to_curve_init(WMADecodeContext *s, int frame_len) #endif } -/* NOTE: We use the same code as Vorbis here */ -/* XXX: optimize it further with SSE/3Dnow */ -static void wma_lsp_to_curve(WMADecodeContext *s, - float *out, float *val_max_ptr, +/** + * NOTE: We use the same code as Vorbis here + * @todo optimize it further with SSE/3Dnow + */ +static void wma_lsp_to_curve(WMACodecContext *s, + float *out, float *val_max_ptr, int n, float *lsp) { int i, j; @@ -626,8 +223,10 @@ static void wma_lsp_to_curve(WMADecodeContext *s, *val_max_ptr = val_max; } -/* decode exponents coded with LSP coefficients (same idea as Vorbis) */ -static void decode_exp_lsp(WMADecodeContext *s, int ch) +/** + * decode exponents coded with LSP coefficients (same idea as Vorbis) + */ +static void decode_exp_lsp(WMACodecContext *s, int ch) { float lsp_coefs[NB_LSP_COEFS]; int val, i; @@ -637,20 +236,22 @@ static void decode_exp_lsp(WMADecodeContext *s, int ch) val = get_bits(&s->gb, 3); else val = get_bits(&s->gb, 4); - lsp_coefs[i] = lsp_codebook[i][val]; + lsp_coefs[i] = ff_wma_lsp_codebook[i][val]; } wma_lsp_to_curve(s, s->exponents[ch], &s->max_exponent[ch], s->block_len, lsp_coefs); } -/* decode exponents coded with VLC codes */ -static int decode_exp_vlc(WMADecodeContext *s, int ch) +/** + * decode exponents coded with VLC codes + */ +static int decode_exp_vlc(WMACodecContext *s, int ch) { int last_exp, n, code; const uint16_t *ptr, *band_ptr; float v, *q, max_scale, *q_end; - + band_ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits]; ptr = band_ptr; q = s->exponents[ch]; @@ -665,10 +266,11 @@ static int decode_exp_vlc(WMADecodeContext *s, int ch) do { *q++ = v; } while (--n); - } - last_exp = 36; + }else + last_exp = 36; + while (q < q_end) { - code = get_vlc(&s->gb, &s->exp_vlc); + code = get_vlc2(&s->gb, s->exp_vlc.table, EXPVLCBITS, EXPMAX); if (code < 0) return -1; /* NOTE: this offset is the same as MPEG4 AAC ! */ @@ -686,24 +288,80 @@ static int decode_exp_vlc(WMADecodeContext *s, int ch) return 0; } -/* return 0 if OK. return 1 if last block of frame. return -1 if - unrecorrable error. */ -static int wma_decode_block(WMADecodeContext *s) + +/** + * Apply MDCT window and add into output. + * + * We ensure that when the windows overlap their squared sum + * is always 1 (MDCT reconstruction rule). + */ +static void wma_window(WMACodecContext *s, float *out) +{ + float *in = s->output; + int block_len, bsize, n; + + /* left part */ + if (s->block_len_bits <= s->prev_block_len_bits) { + block_len = s->block_len; + bsize = s->frame_len_bits - s->block_len_bits; + + s->dsp.vector_fmul_add_add(out, in, s->windows[bsize], + out, 0, block_len, 1); + + } else { + block_len = 1 << s->prev_block_len_bits; + n = (s->block_len - block_len) / 2; + bsize = s->frame_len_bits - s->prev_block_len_bits; + + s->dsp.vector_fmul_add_add(out+n, in+n, s->windows[bsize], + out+n, 0, block_len, 1); + + memcpy(out+n+block_len, in+n+block_len, n*sizeof(float)); + } + + out += s->block_len; + in += s->block_len; + + /* right part */ + if (s->block_len_bits <= s->next_block_len_bits) { + block_len = s->block_len; + bsize = s->frame_len_bits - s->block_len_bits; + + s->dsp.vector_fmul_reverse(out, in, s->windows[bsize], block_len); + + } else { + block_len = 1 << s->next_block_len_bits; + n = (s->block_len - block_len) / 2; + bsize = s->frame_len_bits - s->next_block_len_bits; + + memcpy(out, in, n*sizeof(float)); + + s->dsp.vector_fmul_reverse(out+n, in+n, s->windows[bsize], block_len); + + memset(out+n+block_len, 0, n*sizeof(float)); + } +} + + +/** + * @return 0 if OK. 1 if last block of frame. return -1 if + * unrecorrable error. + */ +static int wma_decode_block(WMACodecContext *s) { int n, v, a, ch, code, bsize; - int coef_nb_bits, total_gain, parse_exponents; - float window[BLOCK_MAX_SIZE * 2]; + int coef_nb_bits, total_gain; int nb_coefs[MAX_CHANNELS]; float mdct_norm; #ifdef TRACE - tprintf("***decode_block: %d:%d\n", s->frame_count - 1, s->block_num); + tprintf(s->avctx, "***decode_block: %d:%d\n", s->frame_count - 1, s->block_num); #endif /* compute current block length */ if (s->use_variable_block_len) { n = av_log2(s->nb_block_sizes - 1) + 1; - + if (s->reset_block_lengths) { s->reset_block_lengths = 0; v = get_bits(&s->gb, n); @@ -736,21 +394,22 @@ static int wma_decode_block(WMADecodeContext *s) return -1; if (s->nb_channels == 2) { - s->ms_stereo = get_bits(&s->gb, 1); + s->ms_stereo = get_bits1(&s->gb); } v = 0; for(ch = 0; ch < s->nb_channels; ch++) { - a = get_bits(&s->gb, 1); + a = get_bits1(&s->gb); s->channel_coded[ch] = a; v |= a; } + + bsize = s->frame_len_bits - s->block_len_bits; + /* if no channel coded, no need to go further */ /* XXX: fix potential framing problems */ if (!v) goto next; - bsize = s->frame_len_bits - s->block_len_bits; - /* read total gain and extract corresponding number of bits for coef escape coding */ total_gain = 1; @@ -760,17 +419,8 @@ static int wma_decode_block(WMADecodeContext *s) if (a != 127) break; } - - if (total_gain < 15) - coef_nb_bits = 13; - else if (total_gain < 32) - coef_nb_bits = 12; - else if (total_gain < 40) - coef_nb_bits = 11; - else if (total_gain < 45) - coef_nb_bits = 10; - else - coef_nb_bits = 9; + + coef_nb_bits= ff_wma_total_gain_to_bits(total_gain); /* compute number of coefficients */ n = s->coefs_end[bsize] - s->coefs_start; @@ -785,7 +435,7 @@ static int wma_decode_block(WMADecodeContext *s) int i, n, a; n = s->exponent_high_sizes[bsize]; for(i=0;igb, 1); + a = get_bits1(&s->gb); s->high_band_coded[ch][i] = a; /* if noise coding, the coefficients are not transmitted */ if (a) @@ -804,7 +454,7 @@ static int wma_decode_block(WMADecodeContext *s) if (val == (int)0x80000000) { val = get_bits(&s->gb, 7) - 19; } else { - code = get_vlc(&s->gb, &s->hgain_vlc); + code = get_vlc2(&s->gb, s->hgain_vlc.table, HGAINVLCBITS, HGAINMAX); if (code < 0) return -1; val += code - 18; @@ -815,14 +465,10 @@ static int wma_decode_block(WMADecodeContext *s) } } } - - /* exposant can be interpolated in short blocks. */ - parse_exponents = 1; - if (s->block_len_bits != s->frame_len_bits) { - parse_exponents = get_bits(&s->gb, 1); - } - - if (parse_exponents) { + + /* exponents can be reused in short blocks. */ + if ((s->block_len_bits == s->frame_len_bits) || + get_bits1(&s->gb)) { for(ch = 0; ch < s->nb_channels; ch++) { if (s->channel_coded[ch]) { if (s->use_exp_vlc) { @@ -831,13 +477,7 @@ static int wma_decode_block(WMADecodeContext *s) } else { decode_exp_lsp(s, ch); } - } - } - } else { - for(ch = 0; ch < s->nb_channels; ch++) { - if (s->channel_coded[ch]) { - interpolate_array(s->exponents[ch], 1 << s->prev_block_len_bits, - s->block_len); + s->exponents_bsize[ch] = bsize; } } } @@ -848,7 +488,7 @@ static int wma_decode_block(WMADecodeContext *s) VLC *coef_vlc; int level, run, sign, tindex; int16_t *ptr, *eptr; - const int16_t *level_table, *run_table; + const uint16_t *level_table, *run_table; /* special VLC tables are used for ms stereo because there is potentially less energy there */ @@ -861,7 +501,7 @@ static int wma_decode_block(WMADecodeContext *s) eptr = ptr + nb_coefs[ch]; memset(ptr, 0, s->block_len * sizeof(int16_t)); for(;;) { - code = get_vlc(&s->gb, coef_vlc); + code = get_vlc2(&s->gb, coef_vlc->table, VLCBITS, VLCMAX); if (code < 0) return -1; if (code == 1) { @@ -878,12 +518,15 @@ static int wma_decode_block(WMADecodeContext *s) run = run_table[code]; level = level_table[code]; } - sign = get_bits(&s->gb, 1); + sign = get_bits1(&s->gb); if (!sign) level = -level; ptr += run; if (ptr >= eptr) - return -1; + { + av_log(NULL, AV_LOG_ERROR, "overflow in spectral RLE, ignoring\n"); + break; + } *ptr++ = level; /* NOTE: EOB can be omitted */ if (ptr >= eptr) @@ -894,7 +537,7 @@ static int wma_decode_block(WMADecodeContext *s) align_get_bits(&s->gb); } } - + /* normalize */ { int n4 = s->block_len / 2; @@ -908,12 +551,13 @@ static int wma_decode_block(WMADecodeContext *s) for(ch = 0; ch < s->nb_channels; ch++) { if (s->channel_coded[ch]) { int16_t *coefs1; - float *coefs, *exponents, mult, mult1, noise, *exp_ptr; - int i, j, n, n1, last_high_band; + float *coefs, *exponents, mult, mult1, noise; + int i, j, n, n1, last_high_band, esize; float exp_power[HIGH_BAND_MAX_SIZE]; coefs1 = s->coefs1[ch]; exponents = s->exponents[ch]; + esize = s->exponents_bsize[ch]; mult = pow(10, total_gain * 0.05) / s->max_exponent[ch]; mult *= mdct_norm; coefs = s->coefs[ch]; @@ -921,41 +565,42 @@ static int wma_decode_block(WMADecodeContext *s) mult1 = mult; /* very low freqs : noise */ for(i = 0;i < s->coefs_start; i++) { - *coefs++ = s->noise_table[s->noise_index] * (*exponents++) * mult1; + *coefs++ = s->noise_table[s->noise_index] * + exponents[i<>esize] * mult1; s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); } - + n1 = s->exponent_high_sizes[bsize]; /* compute power of high bands */ - exp_ptr = exponents + - s->high_band_start[bsize] - - s->coefs_start; + exponents = s->exponents[ch] + + (s->high_band_start[bsize]<exponent_high_bands[s->frame_len_bits - + n = s->exponent_high_bands[s->frame_len_bits - s->block_len_bits][j]; if (s->high_band_coded[ch][j]) { float e2, v; e2 = 0; for(i = 0;i < n; i++) { - v = exp_ptr[i]; + v = exponents[i<>esize]; e2 += v * v; } exp_power[j] = e2 / n; last_high_band = j; - tprintf("%d: power=%f (%d)\n", j, exp_power[j], n); + tprintf(s->avctx, "%d: power=%f (%d)\n", j, exp_power[j], n); } - exp_ptr += n; + exponents += n<exponents[ch] + (s->coefs_start<high_band_start[bsize] - + n = s->high_band_start[bsize] - s->coefs_start; } else { - n = s->exponent_high_bands[s->frame_len_bits - + n = s->exponent_high_bands[s->frame_len_bits - s->block_len_bits][j]; } if (j >= 0 && s->high_band_coded[ch][j]) { @@ -968,21 +613,25 @@ static int wma_decode_block(WMADecodeContext *s) for(i = 0;i < n; i++) { noise = s->noise_table[s->noise_index]; s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); - *coefs++ = (*exponents++) * noise * mult1; + *coefs++ = noise * + exponents[i<>esize] * mult1; } + exponents += n<noise_table[s->noise_index]; s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); - *coefs++ = ((*coefs1++) + noise) * (*exponents++) * mult; + *coefs++ = ((*coefs1++) + noise) * + exponents[i<>esize] * mult; } + exponents += n<block_len - s->coefs_end[bsize]; - mult1 = mult * exponents[-1]; + mult1 = mult * exponents[((-1<>esize]; for(i = 0; i < n; i++) { *coefs++ = s->noise_table[s->noise_index] * mult1; s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); @@ -993,7 +642,7 @@ static int wma_decode_block(WMADecodeContext *s) *coefs++ = 0.0; n = nb_coefs[ch]; for(i = 0;i < n; i++) { - *coefs++ = coefs1[i] * exponents[i] * mult; + *coefs++ = coefs1[i] * exponents[i<>esize] * mult; } n = s->block_len - s->coefs_end[bsize]; for(i = 0;i < n; i++) @@ -1005,12 +654,12 @@ static int wma_decode_block(WMADecodeContext *s) #ifdef TRACE for(ch = 0; ch < s->nb_channels; ch++) { if (s->channel_coded[ch]) { - dump_floats("exponents", 3, s->exponents[ch], s->block_len); - dump_floats("coefs", 1, s->coefs[ch], s->block_len); + dump_floats(s, "exponents", 3, s->exponents[ch], s->block_len); + dump_floats(s, "coefs", 1, s->coefs[ch], s->block_len); } } #endif - + if (s->ms_stereo && s->channel_coded[1]) { float a, b; int i; @@ -1019,11 +668,11 @@ static int wma_decode_block(WMADecodeContext *s) /* no need to optimize this case because it should almost never happen */ if (!s->channel_coded[0]) { - tprintf("rare ms-stereo case happened\n"); + tprintf(s->avctx, "rare ms-stereo case happened\n"); memset(s->coefs[0], 0, sizeof(float) * s->block_len); s->channel_coded[0] = 1; } - + for(i = 0; i < s->block_len; i++) { a = s->coefs[0][i]; b = s->coefs[1][i]; @@ -1032,89 +681,28 @@ static int wma_decode_block(WMADecodeContext *s) } } - /* build the window : we ensure that when the windows overlap - their squared sum is always 1 (MDCT reconstruction rule) */ - /* XXX: merge with output */ - { - int i, next_block_len, block_len, prev_block_len, n; - float *wptr; - - block_len = s->block_len; - prev_block_len = 1 << s->prev_block_len_bits; - next_block_len = 1 << s->next_block_len_bits; - - /* right part */ - wptr = window + block_len; - if (block_len <= next_block_len) { - for(i=0;iwindows[bsize][i]; - } else { - /* overlap */ - n = (block_len / 2) - (next_block_len / 2); - for(i=0;iwindows[s->frame_len_bits - s->next_block_len_bits][i]; - for(i=0;iwindows[bsize][i]; - } else { - /* overlap */ - n = (block_len / 2) - (prev_block_len / 2); - for(i=0;iwindows[s->frame_len_bits - s->prev_block_len_bits][i]; - for(i=0;inb_channels; ch++) { - if (s->channel_coded[ch]) { - FFTSample output[BLOCK_MAX_SIZE * 2] __attribute__((aligned(16))); - float *ptr; - int i, n4, index, n; + int n4, index, n; - n = s->block_len; - n4 = s->block_len / 2; - ff_imdct_calc(&s->mdct_ctx[bsize], - output, s->coefs[ch], s->mdct_tmp); + n = s->block_len; + n4 = s->block_len / 2; + if(s->channel_coded[ch]){ + ff_imdct_calc(&s->mdct_ctx[bsize], s->output, s->coefs[ch]); + }else + memset(s->output, 0, sizeof(s->output)); - /* XXX: optimize all that by build the window and - multipying/adding at the same time */ - /* multiply by the window */ - for(i=0;iframe_len / 2) + s->block_pos - n4; + wma_window(s, &s->frame_out[ch][index]); - /* add in the frame */ - index = (s->frame_len / 2) + s->block_pos - n4; - ptr = &s->frame_out[ch][index]; - for(i=0;ims_stereo && !s->channel_coded[1]) { - ptr = &s->frame_out[1][index]; - for(i=0;ims_stereo && !s->channel_coded[1]) { + wma_window(s, &s->frame_out[1][index]); } } - next: + /* update block number */ s->block_num++; s->block_pos += s->block_len; @@ -1125,14 +713,14 @@ static int wma_decode_block(WMADecodeContext *s) } /* decode a frame of frame_len samples */ -static int wma_decode_frame(WMADecodeContext *s, int16_t *samples) +static int wma_decode_frame(WMACodecContext *s, int16_t *samples) { - int ret, i, n, a, ch, incr; + int ret, i, n, ch, incr; int16_t *ptr; float *iptr; #ifdef TRACE - tprintf("***decode_frame: %d size=%d\n", s->frame_count++, s->frame_len); + tprintf(s->avctx, "***decode_frame: %d size=%d\n", s->frame_count++, s->frame_len); #endif /* read each block */ @@ -1140,7 +728,7 @@ static int wma_decode_frame(WMADecodeContext *s, int16_t *samples) s->block_pos = 0; for(;;) { ret = wma_decode_block(s); - if (ret < 0) + if (ret < 0) return -1; if (ret) break; @@ -1154,71 +742,71 @@ static int wma_decode_frame(WMADecodeContext *s, int16_t *samples) iptr = s->frame_out[ch]; for(i=0;i 32767) - a = 32767; - else if (a < -32768) - a = -32768; - *ptr = a; + *ptr = av_clip_int16(lrintf(*iptr++)); ptr += incr; } /* prepare for next block */ memmove(&s->frame_out[ch][0], &s->frame_out[ch][s->frame_len], s->frame_len * sizeof(float)); - /* XXX: suppress this */ - memset(&s->frame_out[ch][s->frame_len], 0, - s->frame_len * sizeof(float)); } #ifdef TRACE - dump_shorts("samples", samples, n * s->nb_channels); + dump_shorts(s, "samples", samples, n * s->nb_channels); #endif return 0; } -static int wma_decode_superframe(AVCodecContext *avctx, +static int wma_decode_superframe(AVCodecContext *avctx, void *data, int *data_size, - uint8_t *buf, int buf_size) + const uint8_t *buf, int buf_size) { - WMADecodeContext *s = avctx->priv_data; + WMACodecContext *s = avctx->priv_data; int nb_frames, bit_offset, i, pos, len; uint8_t *q; int16_t *samples; - - tprintf("***decode_superframe:\n"); + + tprintf(avctx, "***decode_superframe:\n"); if(buf_size==0){ s->last_superframe_len = 0; return 0; } - + if (buf_size < s->block_align) + return 0; + buf_size = s->block_align; + samples = data; init_get_bits(&s->gb, buf, buf_size*8); - + if (s->use_bit_reservoir) { /* read super frame header */ - get_bits(&s->gb, 4); /* super frame index */ + skip_bits(&s->gb, 4); /* super frame index */ nb_frames = get_bits(&s->gb, 4) - 1; + if((nb_frames+1) * s->nb_channels * s->frame_len * sizeof(int16_t) > *data_size){ + av_log(s->avctx, AV_LOG_ERROR, "Insufficient output space\n"); + goto fail; + } + bit_offset = get_bits(&s->gb, s->byte_offset_bits + 3); if (s->last_superframe_len > 0) { // printf("skip=%d\n", s->last_bitoffset); /* add bit_offset bits to last frame */ - if ((s->last_superframe_len + ((bit_offset + 7) >> 3)) > + if ((s->last_superframe_len + ((bit_offset + 7) >> 3)) > MAX_CODED_SUPERFRAME_SIZE) goto fail; q = s->last_superframe + s->last_superframe_len; len = bit_offset; - while (len > 0) { + while (len > 7) { *q++ = (get_bits)(&s->gb, 8); len -= 8; } if (len > 0) { *q++ = (get_bits)(&s->gb, len) << (8 - len); } - + /* XXX: bit_offset bits into last frame */ init_get_bits(&s->gb, s->last_superframe, MAX_CODED_SUPERFRAME_SIZE*8); /* skip unused bits */ @@ -1237,7 +825,7 @@ static int wma_decode_superframe(AVCodecContext *avctx, len = pos & 7; if (len > 0) skip_bits(&s->gb, len); - + s->reset_block_lengths = 1; for(i=0;ilast_superframe_len = len; memcpy(s->last_superframe, buf + pos, len); } else { + if(s->nb_channels * s->frame_len * sizeof(int16_t) > *data_size){ + av_log(s->avctx, AV_LOG_ERROR, "Insufficient output space\n"); + goto fail; + } /* single frame decode */ if (wma_decode_frame(s, samples) < 0) goto fail; samples += s->nb_channels * s->frame_len; } + +//av_log(NULL, AV_LOG_ERROR, "%d %d %d %d outbytes:%d eaten:%d\n", s->frame_len_bits, s->block_len_bits, s->frame_len, s->block_len, (int8_t *)samples - (int8_t *)data, s->block_align); + *data_size = (int8_t *)samples - (int8_t *)data; return s->block_align; fail: @@ -1269,41 +864,17 @@ static int wma_decode_superframe(AVCodecContext *avctx, return -1; } -static int wma_decode_end(AVCodecContext *avctx) -{ - WMADecodeContext *s = avctx->priv_data; - int i; - - for(i = 0; i < s->nb_block_sizes; i++) - ff_mdct_end(&s->mdct_ctx[i]); - for(i = 0; i < s->nb_block_sizes; i++) - av_free(s->windows[i]); - - if (s->use_exp_vlc) { - free_vlc(&s->exp_vlc); - } - if (s->use_noise_coding) { - free_vlc(&s->hgain_vlc); - } - for(i = 0;i < 2; i++) { - free_vlc(&s->coef_vlc[i]); - av_free(s->run_table[i]); - av_free(s->level_table[i]); - } - - return 0; -} - AVCodec wmav1_decoder = { "wmav1", CODEC_TYPE_AUDIO, CODEC_ID_WMAV1, - sizeof(WMADecodeContext), + sizeof(WMACodecContext), wma_decode_init, NULL, - wma_decode_end, + ff_wma_end, wma_decode_superframe, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"), }; AVCodec wmav2_decoder = @@ -1311,9 +882,10 @@ AVCodec wmav2_decoder = "wmav2", CODEC_TYPE_AUDIO, CODEC_ID_WMAV2, - sizeof(WMADecodeContext), + sizeof(WMACodecContext), wma_decode_init, NULL, - wma_decode_end, + ff_wma_end, wma_decode_superframe, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"), }; diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/wmaenc.c b/src/add-ons/media/plugins/avcodec/libavcodec/wmaenc.c new file mode 100644 index 0000000000..4558947cb3 --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/wmaenc.c @@ -0,0 +1,405 @@ +/* + * WMA compatible encoder + * Copyright (c) 2007 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "wma.h" + +#undef NDEBUG +#include + + +static int encode_init(AVCodecContext * avctx){ + WMACodecContext *s = avctx->priv_data; + int i, flags1, flags2; + uint8_t *extradata; + + s->avctx = avctx; + + if(avctx->channels > MAX_CHANNELS) + return -1; + + if(avctx->bit_rate < 24*1000) + return -1; + + /* extract flag infos */ + flags1 = 0; + flags2 = 1; + if (avctx->codec->id == CODEC_ID_WMAV1) { + extradata= av_malloc(4); + avctx->extradata_size= 4; + AV_WL16(extradata, flags1); + AV_WL16(extradata+2, flags2); + } else if (avctx->codec->id == CODEC_ID_WMAV2) { + extradata= av_mallocz(10); + avctx->extradata_size= 10; + AV_WL32(extradata, flags1); + AV_WL16(extradata+4, flags2); + }else + assert(0); + avctx->extradata= extradata; + s->use_exp_vlc = flags2 & 0x0001; + s->use_bit_reservoir = flags2 & 0x0002; + s->use_variable_block_len = flags2 & 0x0004; + + ff_wma_init(avctx, flags2); + + /* init MDCT */ + for(i = 0; i < s->nb_block_sizes; i++) + ff_mdct_init(&s->mdct_ctx[i], s->frame_len_bits - i + 1, 0); + + avctx->block_align= + s->block_align= avctx->bit_rate*(int64_t)s->frame_len / (avctx->sample_rate*8); +//av_log(NULL, AV_LOG_ERROR, "%d %d %d %d\n", s->block_align, avctx->bit_rate, s->frame_len, avctx->sample_rate); + avctx->frame_size= s->frame_len; + + return 0; +} + + +static void apply_window_and_mdct(AVCodecContext * avctx, signed short * audio, int len) { + WMACodecContext *s = avctx->priv_data; + int window_index= s->frame_len_bits - s->block_len_bits; + int i, j, channel; + const float * win = s->windows[window_index]; + int window_len = 1 << s->block_len_bits; + float n = window_len/2; + + for (channel = 0; channel < avctx->channels; channel++) { + memcpy(s->output, s->frame_out[channel], sizeof(float)*window_len); + j = channel; + for (i = 0; i < len; i++, j += avctx->channels){ + s->output[i+window_len] = audio[j] / n * win[window_len - i - 1]; + s->frame_out[channel][i] = audio[j] / n * win[i]; + } + ff_mdct_calc(&s->mdct_ctx[window_index], s->coefs[channel], s->output); + } +} + +//FIXME use for decoding too +static void init_exp(WMACodecContext *s, int ch, const int *exp_param){ + int n; + const uint16_t *ptr; + float v, *q, max_scale, *q_end; + + ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits]; + q = s->exponents[ch]; + q_end = q + s->block_len; + max_scale = 0; + while (q < q_end) { + /* XXX: use a table */ + v = pow(10, *exp_param++ * (1.0 / 16.0)); + max_scale= FFMAX(max_scale, v); + n = *ptr++; + do { + *q++ = v; + } while (--n); + } + s->max_exponent[ch] = max_scale; +} + +static void encode_exp_vlc(WMACodecContext *s, int ch, const int *exp_param){ + int last_exp; + const uint16_t *ptr; + float *q, *q_end; + + ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits]; + q = s->exponents[ch]; + q_end = q + s->block_len; + if (s->version == 1) { + last_exp= *exp_param++; + assert(last_exp-10 >= 0 && last_exp-10 < 32); + put_bits(&s->pb, 5, last_exp - 10); + q+= *ptr++; + }else + last_exp = 36; + while (q < q_end) { + int exp = *exp_param++; + int code = exp - last_exp + 60; + assert(code >= 0 && code < 120); + put_bits(&s->pb, ff_wma_scale_huffbits[code], ff_wma_scale_huffcodes[code]); + /* XXX: use a table */ + q+= *ptr++; + last_exp= exp; + } +} + +static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], int total_gain){ + int v, bsize, ch, coef_nb_bits, parse_exponents; + float mdct_norm; + int nb_coefs[MAX_CHANNELS]; + static const int fixed_exp[25]={20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20}; + + //FIXME remove duplication relative to decoder + if (s->use_variable_block_len) { + assert(0); //FIXME not implemented + }else{ + /* fixed block len */ + s->next_block_len_bits = s->frame_len_bits; + s->prev_block_len_bits = s->frame_len_bits; + s->block_len_bits = s->frame_len_bits; + } + + s->block_len = 1 << s->block_len_bits; +// assert((s->block_pos + s->block_len) <= s->frame_len); + bsize = s->frame_len_bits - s->block_len_bits; + + //FIXME factor + v = s->coefs_end[bsize] - s->coefs_start; + for(ch = 0; ch < s->nb_channels; ch++) + nb_coefs[ch] = v; + { + int n4 = s->block_len / 2; + mdct_norm = 1.0 / (float)n4; + if (s->version == 1) { + mdct_norm *= sqrt(n4); + } + } + + if (s->nb_channels == 2) { + put_bits(&s->pb, 1, s->ms_stereo= 1); + } + + for(ch = 0; ch < s->nb_channels; ch++) { + if ((s->channel_coded[ch]= 1)) { //FIXME only set channel_coded when needed, instead of always + init_exp(s, ch, fixed_exp); + } + } + + for(ch = 0; ch < s->nb_channels; ch++) { + if (s->channel_coded[ch]) { + int16_t *coefs1; + float *coefs, *exponents, mult; + int i, n; + + coefs1 = s->coefs1[ch]; + exponents = s->exponents[ch]; + mult = pow(10, total_gain * 0.05) / s->max_exponent[ch]; + mult *= mdct_norm; + coefs = src_coefs[ch]; + if (s->use_noise_coding && 0) { + assert(0); //FIXME not implemented + } else { + coefs += s->coefs_start; + n = nb_coefs[ch]; + for(i = 0;i < n; i++){ + double t= *coefs++ / (exponents[i] * mult); + if(t<-32768 || t>32767) + return -1; + + coefs1[i] = lrint(t); + } + } + } + } + + v = 0; + for(ch = 0; ch < s->nb_channels; ch++) { + int a = s->channel_coded[ch]; + put_bits(&s->pb, 1, a); + v |= a; + } + + if (!v) + return 1; + + for(v= total_gain-1; v>=127; v-= 127) + put_bits(&s->pb, 7, 127); + put_bits(&s->pb, 7, v); + + coef_nb_bits= ff_wma_total_gain_to_bits(total_gain); + + if (s->use_noise_coding) { + for(ch = 0; ch < s->nb_channels; ch++) { + if (s->channel_coded[ch]) { + int i, n; + n = s->exponent_high_sizes[bsize]; + for(i=0;ipb, 1, s->high_band_coded[ch][i]= 0); + if (0) + nb_coefs[ch] -= s->exponent_high_bands[bsize][i]; + } + } + } + } + + parse_exponents = 1; + if (s->block_len_bits != s->frame_len_bits) { + put_bits(&s->pb, 1, parse_exponents); + } + + if (parse_exponents) { + for(ch = 0; ch < s->nb_channels; ch++) { + if (s->channel_coded[ch]) { + if (s->use_exp_vlc) { + encode_exp_vlc(s, ch, fixed_exp); + } else { + assert(0); //FIXME not implemented +// encode_exp_lsp(s, ch); + } + } + } + } else { + assert(0); //FIXME not implemented + } + + for(ch = 0; ch < s->nb_channels; ch++) { + if (s->channel_coded[ch]) { + int run, tindex; + int16_t *ptr, *eptr; + tindex = (ch == 1 && s->ms_stereo); + ptr = &s->coefs1[ch][0]; + eptr = ptr + nb_coefs[ch]; + + run=0; + for(;ptr < eptr; ptr++){ + if(*ptr){ + int level= *ptr; + int abs_level= FFABS(level); + int code= 0; + if(abs_level <= s->coef_vlcs[tindex]->max_level){ + if(run < s->coef_vlcs[tindex]->levels[abs_level-1]) + code= run + s->int_table[tindex][abs_level-1]; + } + + assert(code < s->coef_vlcs[tindex]->n); + put_bits(&s->pb, s->coef_vlcs[tindex]->huffbits[code], s->coef_vlcs[tindex]->huffcodes[code]); + + if(code == 0){ + if(1<pb, coef_nb_bits, abs_level); + put_bits(&s->pb, s->frame_len_bits, run); + } + put_bits(&s->pb, 1, level < 0); //FIXME the sign is fliped somewhere + run=0; + }else{ + run++; + } + } + if(run) + put_bits(&s->pb, s->coef_vlcs[tindex]->huffbits[1], s->coef_vlcs[tindex]->huffcodes[1]); + } + if (s->version == 1 && s->nb_channels >= 2) { + align_put_bits(&s->pb); + } + } + return 0; +} + +static int encode_frame(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], uint8_t *buf, int buf_size, int total_gain){ + init_put_bits(&s->pb, buf, buf_size); + + if (s->use_bit_reservoir) { + assert(0);//FIXME not implemented + }else{ + if(encode_block(s, src_coefs, total_gain) < 0) + return INT_MAX; + } + + align_put_bits(&s->pb); + + return put_bits_count(&s->pb)/8 - s->block_align; +} + +static int encode_superframe(AVCodecContext *avctx, + unsigned char *buf, int buf_size, void *data){ + WMACodecContext *s = avctx->priv_data; + short *samples = data; + int i, total_gain; + + s->block_len_bits= s->frame_len_bits; //required by non variable block len + s->block_len = 1 << s->block_len_bits; + + apply_window_and_mdct(avctx, samples, avctx->frame_size); + + if (s->ms_stereo) { + float a, b; + int i; + + for(i = 0; i < s->block_len; i++) { + a = s->coefs[0][i]*0.5; + b = s->coefs[1][i]*0.5; + s->coefs[0][i] = a + b; + s->coefs[1][i] = a - b; + } + } + +#if 1 + total_gain= 128; + for(i=64; i; i>>=1){ + int error= encode_frame(s, s->coefs, buf, buf_size, total_gain-i); + if(error<0) + total_gain-= i; + } +#else + total_gain= 90; + best= encode_frame(s, s->coefs, buf, buf_size, total_gain); + for(i=32; i; i>>=1){ + int scoreL= encode_frame(s, s->coefs, buf, buf_size, total_gain-i); + int scoreR= encode_frame(s, s->coefs, buf, buf_size, total_gain+i); + av_log(NULL, AV_LOG_ERROR, "%d %d %d (%d)\n", scoreL, best, scoreR, total_gain); + if(scoreL < FFMIN(best, scoreR)){ + best = scoreL; + total_gain -= i; + }else if(scoreR < best){ + best = scoreR; + total_gain += i; + } + } +#endif + + encode_frame(s, s->coefs, buf, buf_size, total_gain); + assert((put_bits_count(&s->pb) & 7) == 0); + i= s->block_align - (put_bits_count(&s->pb)+7)/8; + assert(i>=0); + while(i--) + put_bits(&s->pb, 8, 'N'); + + flush_put_bits(&s->pb); + return pbBufPtr(&s->pb) - s->pb.buf; +} + +AVCodec wmav1_encoder = +{ + "wmav1", + CODEC_TYPE_AUDIO, + CODEC_ID_WMAV1, + sizeof(WMACodecContext), + encode_init, + encode_superframe, + ff_wma_end, + .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE}, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"), +}; + +AVCodec wmav2_encoder = +{ + "wmav2", + CODEC_TYPE_AUDIO, + CODEC_ID_WMAV2, + sizeof(WMACodecContext), + encode_init, + encode_superframe, + ff_wma_end, + .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE}, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"), +}; diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/wmv2.c b/src/add-ons/media/plugins/avcodec/libavcodec/wmv2.c index 130a7f89d9..1e29363cf9 100644 --- a/src/add-ons/media/plugins/avcodec/libavcodec/wmv2.c +++ b/src/add-ons/media/plugins/avcodec/libavcodec/wmv2.c @@ -1,611 +1,59 @@ /* * Copyright (c) 2002 The FFmpeg Project. * - * This library is free software; you can redistribute it and/or + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/** - * @file wmv2.c - * wmv2 codec. - */ - +#include "avcodec.h" +#include "mpegvideo.h" +#include "msmpeg4data.h" #include "simple_idct.h" - -#define SKIP_TYPE_NONE 0 -#define SKIP_TYPE_MPEG 1 -#define SKIP_TYPE_ROW 2 -#define SKIP_TYPE_COL 3 +#include "wmv2.h" -typedef struct Wmv2Context{ - MpegEncContext s; - int j_type_bit; - int j_type; - int flag3; - int flag63; - int abt_flag; - int abt_type; - int abt_type_table[6]; - int per_mb_abt; - int per_block_abt; - int mspel_bit; - int cbp_table_index; - int top_left_mv_flag; - int per_mb_rl_bit; - int skip_type; - int hshift; - - ScanTable abt_scantable[2]; - DCTELEM abt_block2[6][64] __align8; -}Wmv2Context; - -static void wmv2_common_init(Wmv2Context * w){ +av_cold void ff_wmv2_common_init(Wmv2Context * w){ MpegEncContext * const s= &w->s; - + ff_init_scantable(s->dsp.idct_permutation, &w->abt_scantable[0], wmv2_scantableA); ff_init_scantable(s->dsp.idct_permutation, &w->abt_scantable[1], wmv2_scantableB); } -static int encode_ext_header(Wmv2Context *w){ - MpegEncContext * const s= &w->s; - PutBitContext pb; - int code; - - init_put_bits(&pb, s->avctx->extradata, s->avctx->extradata_size); - - put_bits(&pb, 5, s->avctx->frame_rate / s->avctx->frame_rate_base); //yes 29.97 -> 29 - put_bits(&pb, 11, FFMIN(s->bit_rate/1024, 2047)); - - put_bits(&pb, 1, w->mspel_bit=1); - put_bits(&pb, 1, w->flag3=1); - put_bits(&pb, 1, w->abt_flag=1); - put_bits(&pb, 1, w->j_type_bit=1); - put_bits(&pb, 1, w->top_left_mv_flag=0); - put_bits(&pb, 1, w->per_mb_rl_bit=1); - put_bits(&pb, 3, code=1); - - flush_put_bits(&pb); - - s->slice_height = s->mb_height / code; - - return 0; -} - -#ifdef CONFIG_ENCODERS -static int wmv2_encode_init(AVCodecContext *avctx){ - Wmv2Context * const w= avctx->priv_data; - - if(MPV_encode_init(avctx) < 0) - return -1; - - wmv2_common_init(w); - - avctx->extradata_size= 4; - avctx->extradata= av_mallocz(avctx->extradata_size + 10); - encode_ext_header(w); - - return 0; -} - -static int wmv2_encode_end(AVCodecContext *avctx){ - - if(MPV_encode_end(avctx) < 0) - return -1; - - avctx->extradata_size= 0; - av_freep(&avctx->extradata); - - return 0; -} - -int ff_wmv2_encode_picture_header(MpegEncContext * s, int picture_number) -{ - Wmv2Context * const w= (Wmv2Context*)s; - - put_bits(&s->pb, 1, s->pict_type - 1); - if(s->pict_type == I_TYPE){ - put_bits(&s->pb, 7, 0); - } - put_bits(&s->pb, 5, s->qscale); - - s->dc_table_index = 1; - s->mv_table_index = 1; /* only if P frame */ -// s->use_skip_mb_code = 1; /* only if P frame */ - s->per_mb_rl_table = 0; - s->mspel= 0; - w->per_mb_abt=0; - w->abt_type=0; - w->j_type=0; - - assert(s->flipflop_rounding); - - if (s->pict_type == I_TYPE) { - assert(s->no_rounding==1); - if(w->j_type_bit) put_bits(&s->pb, 1, w->j_type); - - if(w->per_mb_rl_bit) put_bits(&s->pb, 1, s->per_mb_rl_table); - - if(!s->per_mb_rl_table){ - code012(&s->pb, s->rl_chroma_table_index); - code012(&s->pb, s->rl_table_index); - } - - put_bits(&s->pb, 1, s->dc_table_index); - - s->inter_intra_pred= 0; - }else{ - int cbp_index; - - put_bits(&s->pb, 2, SKIP_TYPE_NONE); - - code012(&s->pb, cbp_index=0); - if(s->qscale <= 10){ - int map[3]= {0,2,1}; - w->cbp_table_index= map[cbp_index]; - }else if(s->qscale <= 20){ - int map[3]= {1,0,2}; - w->cbp_table_index= map[cbp_index]; - }else{ - int map[3]= {2,1,0}; - w->cbp_table_index= map[cbp_index]; - } - - if(w->mspel_bit) put_bits(&s->pb, 1, s->mspel); - - if(w->abt_flag){ - put_bits(&s->pb, 1, w->per_mb_abt^1); - if(!w->per_mb_abt){ - code012(&s->pb, w->abt_type); - } - } - - if(w->per_mb_rl_bit) put_bits(&s->pb, 1, s->per_mb_rl_table); - - if(!s->per_mb_rl_table){ - code012(&s->pb, s->rl_table_index); - s->rl_chroma_table_index = s->rl_table_index; - } - put_bits(&s->pb, 1, s->dc_table_index); - put_bits(&s->pb, 1, s->mv_table_index); - - s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE); - } - s->esc3_level_length= 0; - s->esc3_run_length= 0; - - return 0; -} - -// nearly idential to wmv1 but thats just because we dont use the useless M$ crap features -// its duplicated here in case someone wants to add support for these carp features -void ff_wmv2_encode_mb(MpegEncContext * s, - DCTELEM block[6][64], - int motion_x, int motion_y) -{ - Wmv2Context * const w= (Wmv2Context*)s; - int cbp, coded_cbp, i; - int pred_x, pred_y; - uint8_t *coded_block; - - handle_slices(s); - - if (!s->mb_intra) { - /* compute cbp */ - set_stat(ST_INTER_MB); - cbp = 0; - for (i = 0; i < 6; i++) { - if (s->block_last_index[i] >= 0) - cbp |= 1 << (5 - i); - } - - put_bits(&s->pb, - wmv2_inter_table[w->cbp_table_index][cbp + 64][1], - wmv2_inter_table[w->cbp_table_index][cbp + 64][0]); - - /* motion vector */ - h263_pred_motion(s, 0, &pred_x, &pred_y); - msmpeg4_encode_motion(s, motion_x - pred_x, - motion_y - pred_y); - } else { - /* compute cbp */ - cbp = 0; - coded_cbp = 0; - for (i = 0; i < 6; i++) { - int val, pred; - val = (s->block_last_index[i] >= 1); - cbp |= val << (5 - i); - if (i < 4) { - /* predict value for close blocks only for luma */ - pred = coded_block_pred(s, i, &coded_block); - *coded_block = val; - val = val ^ pred; - } - coded_cbp |= val << (5 - i); - } -#if 0 - if (coded_cbp) - printf("cbp=%x %x\n", cbp, coded_cbp); -#endif - - if (s->pict_type == I_TYPE) { - set_stat(ST_INTRA_MB); - put_bits(&s->pb, - table_mb_intra[coded_cbp][1], table_mb_intra[coded_cbp][0]); - } else { - put_bits(&s->pb, - wmv2_inter_table[w->cbp_table_index][cbp][1], - wmv2_inter_table[w->cbp_table_index][cbp][0]); - } - set_stat(ST_INTRA_MB); - put_bits(&s->pb, 1, 0); /* no AC prediction yet */ - if(s->inter_intra_pred){ - s->h263_aic_dir=0; - put_bits(&s->pb, table_inter_intra[s->h263_aic_dir][1], table_inter_intra[s->h263_aic_dir][0]); - } - } - - for (i = 0; i < 6; i++) { - msmpeg4_encode_block(s, block[i], i); - } -} -#endif //CONFIG_ENCODERS - -static void parse_mb_skip(Wmv2Context * w){ - int mb_x, mb_y; - MpegEncContext * const s= &w->s; - uint32_t * const mb_type= s->current_picture_ptr->mb_type; - - w->skip_type= get_bits(&s->gb, 2); - switch(w->skip_type){ - case SKIP_TYPE_NONE: - for(mb_y=0; mb_ymb_height; mb_y++){ - for(mb_x=0; mb_xmb_width; mb_x++){ - mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_16x16 | MB_TYPE_L0; - } - } - break; - case SKIP_TYPE_MPEG: - for(mb_y=0; mb_ymb_height; mb_y++){ - for(mb_x=0; mb_xmb_width; mb_x++){ - mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; - } - } - break; - case SKIP_TYPE_ROW: - for(mb_y=0; mb_ymb_height; mb_y++){ - if(get_bits1(&s->gb)){ - for(mb_x=0; mb_xmb_width; mb_x++){ - mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; - } - }else{ - for(mb_x=0; mb_xmb_width; mb_x++){ - mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; - } - } - } - break; - case SKIP_TYPE_COL: - for(mb_x=0; mb_xmb_width; mb_x++){ - if(get_bits1(&s->gb)){ - for(mb_y=0; mb_ymb_height; mb_y++){ - mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; - } - }else{ - for(mb_y=0; mb_ymb_height; mb_y++){ - mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; - } - } - } - break; - } -} - -static int decode_ext_header(Wmv2Context *w){ - MpegEncContext * const s= &w->s; - GetBitContext gb; - int fps; - int code; - - if(s->avctx->extradata_size<4) return -1; - - init_get_bits(&gb, s->avctx->extradata, s->avctx->extradata_size*8); - - fps = get_bits(&gb, 5); - s->bit_rate = get_bits(&gb, 11)*1024; - w->mspel_bit = get_bits1(&gb); - w->flag3 = get_bits1(&gb); - w->abt_flag = get_bits1(&gb); - w->j_type_bit = get_bits1(&gb); - w->top_left_mv_flag= get_bits1(&gb); - w->per_mb_rl_bit = get_bits1(&gb); - code = get_bits(&gb, 3); - - if(code==0) return -1; - - s->slice_height = s->mb_height / code; - - if(s->avctx->debug&FF_DEBUG_PICT_INFO){ - av_log(s->avctx, AV_LOG_DEBUG, "fps:%d, br:%d, qpbit:%d, abt_flag:%d, j_type_bit:%d, tl_mv_flag:%d, mbrl_bit:%d, code:%d, flag3:%d, slices:%d\n", - fps, s->bit_rate, w->mspel_bit, w->abt_flag, w->j_type_bit, w->top_left_mv_flag, w->per_mb_rl_bit, code, w->flag3, - code); - } - return 0; -} - -int ff_wmv2_decode_picture_header(MpegEncContext * s) -{ - Wmv2Context * const w= (Wmv2Context*)s; - int code; - -#if 0 -{ -int i; -for(i=0; igb.size*8; i++) - printf("%d", get_bits1(&s->gb)); -// get_bits1(&s->gb); -printf("END\n"); -return -1; -} -#endif - if(s->picture_number==0) - decode_ext_header(w); - - s->pict_type = get_bits(&s->gb, 1) + 1; - if(s->pict_type == I_TYPE){ - code = get_bits(&s->gb, 7); - av_log(s->avctx, AV_LOG_ERROR, "I7:%X/\n", code); - } - s->chroma_qscale= s->qscale = get_bits(&s->gb, 5); - if(s->qscale < 0) - return -1; - - return 0; -} - -int ff_wmv2_decode_secondary_picture_header(MpegEncContext * s) -{ - Wmv2Context * const w= (Wmv2Context*)s; - - if (s->pict_type == I_TYPE) { - if(w->j_type_bit) w->j_type= get_bits1(&s->gb); - else w->j_type= 0; //FIXME check - - if(!w->j_type){ - if(w->per_mb_rl_bit) s->per_mb_rl_table= get_bits1(&s->gb); - else s->per_mb_rl_table= 0; - - if(!s->per_mb_rl_table){ - s->rl_chroma_table_index = decode012(&s->gb); - s->rl_table_index = decode012(&s->gb); - } - - s->dc_table_index = get_bits1(&s->gb); - } - s->inter_intra_pred= 0; - s->no_rounding = 1; - if(s->avctx->debug&FF_DEBUG_PICT_INFO){ - av_log(s->avctx, AV_LOG_DEBUG, "qscale:%d rlc:%d rl:%d dc:%d mbrl:%d j_type:%d \n", - s->qscale, - s->rl_chroma_table_index, - s->rl_table_index, - s->dc_table_index, - s->per_mb_rl_table, - w->j_type); - } - }else{ - int cbp_index; - w->j_type=0; - - parse_mb_skip(w); - cbp_index= decode012(&s->gb); - if(s->qscale <= 10){ - int map[3]= {0,2,1}; - w->cbp_table_index= map[cbp_index]; - }else if(s->qscale <= 20){ - int map[3]= {1,0,2}; - w->cbp_table_index= map[cbp_index]; - }else{ - int map[3]= {2,1,0}; - w->cbp_table_index= map[cbp_index]; - } - - if(w->mspel_bit) s->mspel= get_bits1(&s->gb); - else s->mspel= 0; //FIXME check - - if(w->abt_flag){ - w->per_mb_abt= get_bits1(&s->gb)^1; - if(!w->per_mb_abt){ - w->abt_type= decode012(&s->gb); - } - } - - if(w->per_mb_rl_bit) s->per_mb_rl_table= get_bits1(&s->gb); - else s->per_mb_rl_table= 0; - - if(!s->per_mb_rl_table){ - s->rl_table_index = decode012(&s->gb); - s->rl_chroma_table_index = s->rl_table_index; - } - - s->dc_table_index = get_bits1(&s->gb); - s->mv_table_index = get_bits1(&s->gb); - - s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE); - s->no_rounding ^= 1; - - if(s->avctx->debug&FF_DEBUG_PICT_INFO){ - av_log(s->avctx, AV_LOG_DEBUG, "rl:%d rlc:%d dc:%d mv:%d mbrl:%d qp:%d mspel:%d per_mb_abt:%d abt_type:%d cbp:%d ii:%d\n", - s->rl_table_index, - s->rl_chroma_table_index, - s->dc_table_index, - s->mv_table_index, - s->per_mb_rl_table, - s->qscale, - s->mspel, - w->per_mb_abt, - w->abt_type, - w->cbp_table_index, - s->inter_intra_pred); - } - } - s->esc3_level_length= 0; - s->esc3_run_length= 0; - -s->picture_number++; //FIXME ? - - -// if(w->j_type) -// return wmv2_decode_j_picture(w); //FIXME - - if(w->j_type){ - av_log(s->avctx, AV_LOG_ERROR, "J-type picture isnt supported\n"); - return -1; - } - - return 0; -} - -static void ff_wmv2_decode_init(MpegEncContext *s){ -} - -static inline int wmv2_decode_motion(Wmv2Context *w, int *mx_ptr, int *my_ptr){ - MpegEncContext * const s= &w->s; - int ret; - - ret= msmpeg4_decode_motion(s, mx_ptr, my_ptr); - - if(ret<0) return -1; - - if((((*mx_ptr)|(*my_ptr)) & 1) && s->mspel) - w->hshift= get_bits1(&s->gb); - else - w->hshift= 0; - -//printf("%d %d ", *mx_ptr, *my_ptr); - - return 0; -} - -static int16_t *wmv2_pred_motion(Wmv2Context *w, int *px, int *py){ - MpegEncContext * const s= &w->s; - int xy, wrap, diff, type; - int16_t *A, *B, *C, *mot_val; - - wrap = s->block_wrap[0]; - xy = s->block_index[0]; - - mot_val = s->current_picture.motion_val[0][xy]; - - A = s->current_picture.motion_val[0][xy - 1]; - B = s->current_picture.motion_val[0][xy - wrap]; - C = s->current_picture.motion_val[0][xy + 2 - wrap]; - - diff= FFMAX(ABS(A[0] - B[0]), ABS(A[1] - B[1])); - - if(s->mb_x && !s->first_slice_line && !s->mspel && w->top_left_mv_flag && diff >= 8) - type= get_bits1(&s->gb); - else - type= 2; - - if(type == 0){ - *px= A[0]; - *py= A[1]; - }else if(type == 1){ - *px= B[0]; - *py= B[1]; - }else{ - /* special case for first (slice) line */ - if (s->first_slice_line) { - *px = A[0]; - *py = A[1]; - } else { - *px = mid_pred(A[0], B[0], C[0]); - *py = mid_pred(A[1], B[1], C[1]); - } - } - - return mot_val; -} - -static inline int wmv2_decode_inter_block(Wmv2Context *w, DCTELEM *block, int n, int cbp){ - MpegEncContext * const s= &w->s; - static const int sub_cbp_table[3]= {2,3,1}; - int sub_cbp; - - if(!cbp){ - s->block_last_index[n] = -1; - - return 0; - } - - if(w->per_block_abt) - w->abt_type= decode012(&s->gb); -#if 0 - if(w->per_block_abt) - printf("B%d", w->abt_type); -#endif - w->abt_type_table[n]= w->abt_type; - - if(w->abt_type){ -// const uint8_t *scantable= w->abt_scantable[w->abt_type-1].permutated; - const uint8_t *scantable= w->abt_scantable[w->abt_type-1].scantable; -// const uint8_t *scantable= w->abt_type-1 ? w->abt_scantable[1].permutated : w->abt_scantable[0].scantable; - - sub_cbp= sub_cbp_table[ decode012(&s->gb) ]; -// printf("S%d", sub_cbp); - - if(sub_cbp&1){ - if (msmpeg4_decode_block(s, block, n, 1, scantable) < 0) - return -1; - } - - if(sub_cbp&2){ - if (msmpeg4_decode_block(s, w->abt_block2[n], n, 1, scantable) < 0) - return -1; - } - s->block_last_index[n] = 63; - - return 0; - }else{ - return msmpeg4_decode_block(s, block, n, 1, s->inter_scantable.permutated); - } -} - static void wmv2_add_block(Wmv2Context *w, DCTELEM *block1, uint8_t *dst, int stride, int n){ MpegEncContext * const s= &w->s; + if (s->block_last_index[n] >= 0) { switch(w->abt_type_table[n]){ case 0: - if (s->block_last_index[n] >= 0) { - s->dsp.idct_add (dst, stride, block1); - } + s->dsp.idct_add (dst, stride, block1); break; case 1: - simple_idct84_add(dst , stride, block1); - simple_idct84_add(dst + 4*stride, stride, w->abt_block2[n]); + ff_simple_idct84_add(dst , stride, block1); + ff_simple_idct84_add(dst + 4*stride, stride, w->abt_block2[n]); memset(w->abt_block2[n], 0, 64*sizeof(DCTELEM)); break; case 2: - simple_idct48_add(dst , stride, block1); - simple_idct48_add(dst + 4 , stride, w->abt_block2[n]); + ff_simple_idct48_add(dst , stride, block1); + ff_simple_idct48_add(dst + 4 , stride, w->abt_block2[n]); memset(w->abt_block2[n], 0, 64*sizeof(DCTELEM)); break; default: av_log(s->avctx, AV_LOG_ERROR, "internal error in WMV2 abt\n"); } + } } void ff_wmv2_add_mb(MpegEncContext *s, DCTELEM block1[6][64], uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr){ @@ -615,9 +63,9 @@ void ff_wmv2_add_mb(MpegEncContext *s, DCTELEM block1[6][64], uint8_t *dest_y, u wmv2_add_block(w, block1[1], dest_y + 8 , s->linesize, 1); wmv2_add_block(w, block1[2], dest_y + 8*s->linesize, s->linesize, 2); wmv2_add_block(w, block1[3], dest_y + 8 + 8*s->linesize, s->linesize, 3); - + if(s->flags&CODEC_FLAG_GRAY) return; - + wmv2_add_block(w, block1[4], dest_cb , s->uvlinesize, 4); wmv2_add_block(w, block1[5], dest_cr , s->uvlinesize, 5); } @@ -631,16 +79,22 @@ void ff_mspel_motion(MpegEncContext *s, uint8_t *ptr; int dxy, offset, mx, my, src_x, src_y, v_edge_pos, linesize, uvlinesize; int emu=0; - + dxy = ((motion_y & 1) << 1) | (motion_x & 1); dxy = 2*dxy + w->hshift; src_x = s->mb_x * 16 + (motion_x >> 1); src_y = s->mb_y * 16 + (motion_y >> 1); - + /* WARNING: do no forget half pels */ v_edge_pos = s->v_edge_pos; - src_x = clip(src_x, -16, s->width); - src_y = clip(src_y, -16, s->height); + src_x = av_clip(src_x, -16, s->width); + src_y = av_clip(src_y, -16, s->height); + + if(src_x<=-16 || src_x >= s->width) + dxy &= ~3; + if(src_y<=-16 || src_y >= s->height) + dxy &= ~4; + linesize = s->linesize; uvlinesize = s->uvlinesize; ptr = ref_picture[0] + (src_y * linesize) + src_x; @@ -648,7 +102,7 @@ void ff_mspel_motion(MpegEncContext *s, if(s->flags&CODEC_FLAG_EMU_EDGE){ if(src_x<1 || src_y<1 || src_x + 17 >= s->h_edge_pos || src_y + h+1 >= v_edge_pos){ - ff_emulated_edge_mc(s->edge_emu_buffer, ptr - 1 - s->linesize, s->linesize, 19, 19, + ff_emulated_edge_mc(s->edge_emu_buffer, ptr - 1 - s->linesize, s->linesize, 19, 19, src_x-1, src_y-1, s->h_edge_pos, s->v_edge_pos); ptr= s->edge_emu_buffer + 1 + s->linesize; emu=1; @@ -677,19 +131,19 @@ void ff_mspel_motion(MpegEncContext *s, mx >>= 1; my >>= 1; } - + src_x = s->mb_x * 8 + mx; src_y = s->mb_y * 8 + my; - src_x = clip(src_x, -8, s->width >> 1); + src_x = av_clip(src_x, -8, s->width >> 1); if (src_x == (s->width >> 1)) dxy &= ~1; - src_y = clip(src_y, -8, s->height >> 1); + src_y = av_clip(src_y, -8, s->height >> 1); if (src_y == (s->height >> 1)) dxy &= ~2; offset = (src_y * uvlinesize) + src_x; ptr = ref_picture[1] + offset; if(emu){ - ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, + ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); ptr= s->edge_emu_buffer; } @@ -697,154 +151,9 @@ void ff_mspel_motion(MpegEncContext *s, ptr = ref_picture[2] + offset; if(emu){ - ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, + ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); ptr= s->edge_emu_buffer; } pix_op[1][dxy](dest_cr, ptr, uvlinesize, h >> 1); } - - -static int wmv2_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) -{ - Wmv2Context * const w= (Wmv2Context*)s; - int cbp, code, i; - uint8_t *coded_val; - - if(w->j_type) return 0; - - if (s->pict_type == P_TYPE) { - if(IS_SKIP(s->current_picture.mb_type[s->mb_y * s->mb_stride + s->mb_x])){ - /* skip mb */ - s->mb_intra = 0; - for(i=0;i<6;i++) - s->block_last_index[i] = -1; - s->mv_dir = MV_DIR_FORWARD; - s->mv_type = MV_TYPE_16X16; - s->mv[0][0][0] = 0; - s->mv[0][0][1] = 0; - s->mb_skiped = 1; - w->hshift=0; - return 0; - } - - code = get_vlc2(&s->gb, mb_non_intra_vlc[w->cbp_table_index].table, MB_NON_INTRA_VLC_BITS, 3); - if (code < 0) - return -1; - s->mb_intra = (~code & 0x40) >> 6; - - cbp = code & 0x3f; - } else { - s->mb_intra = 1; - code = get_vlc2(&s->gb, mb_intra_vlc.table, MB_INTRA_VLC_BITS, 2); - if (code < 0){ - av_log(s->avctx, AV_LOG_ERROR, "II-cbp illegal at %d %d\n", s->mb_x, s->mb_y); - return -1; - } - /* predict coded block pattern */ - cbp = 0; - for(i=0;i<6;i++) { - int val = ((code >> (5 - i)) & 1); - if (i < 4) { - int pred = coded_block_pred(s, i, &coded_val); - val = val ^ pred; - *coded_val = val; - } - cbp |= val << (5 - i); - } - } - - if (!s->mb_intra) { - int mx, my; -//printf("P at %d %d\n", s->mb_x, s->mb_y); - wmv2_pred_motion(w, &mx, &my); - - if(cbp){ - if(s->per_mb_rl_table){ - s->rl_table_index = decode012(&s->gb); - s->rl_chroma_table_index = s->rl_table_index; - } - - if(w->abt_flag && w->per_mb_abt){ - w->per_block_abt= get_bits1(&s->gb); - if(!w->per_block_abt) - w->abt_type= decode012(&s->gb); - }else - w->per_block_abt=0; - } - - if (wmv2_decode_motion(w, &mx, &my) < 0) - return -1; - - s->mv_dir = MV_DIR_FORWARD; - s->mv_type = MV_TYPE_16X16; - s->mv[0][0][0] = mx; - s->mv[0][0][1] = my; - - for (i = 0; i < 6; i++) { - if (wmv2_decode_inter_block(w, block[i], i, (cbp >> (5 - i)) & 1) < 0) - { - av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding inter block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); - return -1; - } - } - } else { -//if(s->pict_type==P_TYPE) -// printf("%d%d ", s->inter_intra_pred, cbp); -//printf("I at %d %d %d %06X\n", s->mb_x, s->mb_y, ((cbp&3)? 1 : 0) +((cbp&0x3C)? 2 : 0), show_bits(&s->gb, 24)); - s->ac_pred = get_bits1(&s->gb); - if(s->inter_intra_pred){ - s->h263_aic_dir= get_vlc2(&s->gb, inter_intra_vlc.table, INTER_INTRA_VLC_BITS, 1); -// printf("%d%d %d %d/", s->ac_pred, s->h263_aic_dir, s->mb_x, s->mb_y); - } - if(s->per_mb_rl_table && cbp){ - s->rl_table_index = decode012(&s->gb); - s->rl_chroma_table_index = s->rl_table_index; - } - - for (i = 0; i < 6; i++) { - if (msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0) - { - av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding intra block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); - return -1; - } - } - } - - return 0; -} - -static int wmv2_decode_init(AVCodecContext *avctx){ - Wmv2Context * const w= avctx->priv_data; - - if(ff_h263_decode_init(avctx) < 0) - return -1; - - wmv2_common_init(w); - - return 0; -} - -AVCodec wmv2_decoder = { - "wmv2", - CODEC_TYPE_VIDEO, - CODEC_ID_WMV2, - sizeof(Wmv2Context), - wmv2_decode_init, - NULL, - ff_h263_decode_end, - ff_h263_decode_frame, - CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, -}; - -#ifdef CONFIG_ENCODERS -AVCodec wmv2_encoder = { - "wmv2", - CODEC_TYPE_VIDEO, - CODEC_ID_WMV2, - sizeof(Wmv2Context), - wmv2_encode_init, - MPV_encode_picture, - MPV_encode_end, -}; -#endif diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/wmv2.h b/src/add-ons/media/plugins/avcodec/libavcodec/wmv2.h new file mode 100644 index 0000000000..9d43ec547e --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/wmv2.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2002 The FFmpeg Project. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FFMPEG_WMV2_H +#define FFMPEG_WMV2_H + +#include "avcodec.h" +#include "dsputil.h" +#include "mpegvideo.h" +#include "intrax8.h" + +#define SKIP_TYPE_NONE 0 +#define SKIP_TYPE_MPEG 1 +#define SKIP_TYPE_ROW 2 +#define SKIP_TYPE_COL 3 + + +typedef struct Wmv2Context{ + MpegEncContext s; + IntraX8Context x8; + int j_type_bit; + int j_type; + int abt_flag; + int abt_type; + int abt_type_table[6]; + int per_mb_abt; + int per_block_abt; + int mspel_bit; + int cbp_table_index; + int top_left_mv_flag; + int per_mb_rl_bit; + int skip_type; + int hshift; + + ScanTable abt_scantable[2]; + DECLARE_ALIGNED_16(DCTELEM, abt_block2[6][64]); +}Wmv2Context; + +void ff_wmv2_common_init(Wmv2Context * w); + +#endif /* FFMPEG_WMV2_H */ diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/wmv2dec.c b/src/add-ons/media/plugins/avcodec/libavcodec/wmv2dec.c new file mode 100644 index 0000000000..696d73bcce --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/wmv2dec.c @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2002 The FFmpeg Project. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "dsputil.h" +#include "mpegvideo.h" +#include "msmpeg4.h" +#include "msmpeg4data.h" +#include "intrax8.h" +#include "wmv2.h" + + +static void parse_mb_skip(Wmv2Context * w){ + int mb_x, mb_y; + MpegEncContext * const s= &w->s; + uint32_t * const mb_type= s->current_picture_ptr->mb_type; + + w->skip_type= get_bits(&s->gb, 2); + switch(w->skip_type){ + case SKIP_TYPE_NONE: + for(mb_y=0; mb_ymb_height; mb_y++){ + for(mb_x=0; mb_xmb_width; mb_x++){ + mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_16x16 | MB_TYPE_L0; + } + } + break; + case SKIP_TYPE_MPEG: + for(mb_y=0; mb_ymb_height; mb_y++){ + for(mb_x=0; mb_xmb_width; mb_x++){ + mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; + } + } + break; + case SKIP_TYPE_ROW: + for(mb_y=0; mb_ymb_height; mb_y++){ + if(get_bits1(&s->gb)){ + for(mb_x=0; mb_xmb_width; mb_x++){ + mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; + } + }else{ + for(mb_x=0; mb_xmb_width; mb_x++){ + mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; + } + } + } + break; + case SKIP_TYPE_COL: + for(mb_x=0; mb_xmb_width; mb_x++){ + if(get_bits1(&s->gb)){ + for(mb_y=0; mb_ymb_height; mb_y++){ + mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; + } + }else{ + for(mb_y=0; mb_ymb_height; mb_y++){ + mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; + } + } + } + break; + } +} + +static int decode_ext_header(Wmv2Context *w){ + MpegEncContext * const s= &w->s; + GetBitContext gb; + int fps; + int code; + + if(s->avctx->extradata_size<4) return -1; + + init_get_bits(&gb, s->avctx->extradata, s->avctx->extradata_size*8); + + fps = get_bits(&gb, 5); + s->bit_rate = get_bits(&gb, 11)*1024; + w->mspel_bit = get_bits1(&gb); + s->loop_filter = get_bits1(&gb); + w->abt_flag = get_bits1(&gb); + w->j_type_bit = get_bits1(&gb); + w->top_left_mv_flag= get_bits1(&gb); + w->per_mb_rl_bit = get_bits1(&gb); + code = get_bits(&gb, 3); + + if(code==0) return -1; + + s->slice_height = s->mb_height / code; + + if(s->avctx->debug&FF_DEBUG_PICT_INFO){ + av_log(s->avctx, AV_LOG_DEBUG, "fps:%d, br:%d, qpbit:%d, abt_flag:%d, j_type_bit:%d, tl_mv_flag:%d, mbrl_bit:%d, code:%d, loop_filter:%d, slices:%d\n", + fps, s->bit_rate, w->mspel_bit, w->abt_flag, w->j_type_bit, w->top_left_mv_flag, w->per_mb_rl_bit, code, s->loop_filter, + code); + } + return 0; +} + +int ff_wmv2_decode_picture_header(MpegEncContext * s) +{ + Wmv2Context * const w= (Wmv2Context*)s; + int code; + +#if 0 +{ +int i; +for(i=0; igb.size*8; i++) + printf("%d", get_bits1(&s->gb)); +// get_bits1(&s->gb); +printf("END\n"); +return -1; +} +#endif + if(s->picture_number==0) + decode_ext_header(w); + + s->pict_type = get_bits1(&s->gb) + 1; + if(s->pict_type == FF_I_TYPE){ + code = get_bits(&s->gb, 7); + av_log(s->avctx, AV_LOG_DEBUG, "I7:%X/\n", code); + } + s->chroma_qscale= s->qscale = get_bits(&s->gb, 5); + if(s->qscale <= 0) + return -1; + + return 0; +} + +int ff_wmv2_decode_secondary_picture_header(MpegEncContext * s) +{ + Wmv2Context * const w= (Wmv2Context*)s; + + if (s->pict_type == FF_I_TYPE) { + if(w->j_type_bit) w->j_type= get_bits1(&s->gb); + else w->j_type= 0; //FIXME check + + if(!w->j_type){ + if(w->per_mb_rl_bit) s->per_mb_rl_table= get_bits1(&s->gb); + else s->per_mb_rl_table= 0; + + if(!s->per_mb_rl_table){ + s->rl_chroma_table_index = decode012(&s->gb); + s->rl_table_index = decode012(&s->gb); + } + + s->dc_table_index = get_bits1(&s->gb); + } + s->inter_intra_pred= 0; + s->no_rounding = 1; + if(s->avctx->debug&FF_DEBUG_PICT_INFO){ + av_log(s->avctx, AV_LOG_DEBUG, "qscale:%d rlc:%d rl:%d dc:%d mbrl:%d j_type:%d \n", + s->qscale, + s->rl_chroma_table_index, + s->rl_table_index, + s->dc_table_index, + s->per_mb_rl_table, + w->j_type); + } + }else{ + int cbp_index; + w->j_type=0; + + parse_mb_skip(w); + cbp_index= decode012(&s->gb); + if(s->qscale <= 10){ + int map[3]= {0,2,1}; + w->cbp_table_index= map[cbp_index]; + }else if(s->qscale <= 20){ + int map[3]= {1,0,2}; + w->cbp_table_index= map[cbp_index]; + }else{ + int map[3]= {2,1,0}; + w->cbp_table_index= map[cbp_index]; + } + + if(w->mspel_bit) s->mspel= get_bits1(&s->gb); + else s->mspel= 0; //FIXME check + + if(w->abt_flag){ + w->per_mb_abt= get_bits1(&s->gb)^1; + if(!w->per_mb_abt){ + w->abt_type= decode012(&s->gb); + } + } + + if(w->per_mb_rl_bit) s->per_mb_rl_table= get_bits1(&s->gb); + else s->per_mb_rl_table= 0; + + if(!s->per_mb_rl_table){ + s->rl_table_index = decode012(&s->gb); + s->rl_chroma_table_index = s->rl_table_index; + } + + s->dc_table_index = get_bits1(&s->gb); + s->mv_table_index = get_bits1(&s->gb); + + s->inter_intra_pred= 0;//(s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE); + s->no_rounding ^= 1; + + if(s->avctx->debug&FF_DEBUG_PICT_INFO){ + av_log(s->avctx, AV_LOG_DEBUG, "rl:%d rlc:%d dc:%d mv:%d mbrl:%d qp:%d mspel:%d per_mb_abt:%d abt_type:%d cbp:%d ii:%d\n", + s->rl_table_index, + s->rl_chroma_table_index, + s->dc_table_index, + s->mv_table_index, + s->per_mb_rl_table, + s->qscale, + s->mspel, + w->per_mb_abt, + w->abt_type, + w->cbp_table_index, + s->inter_intra_pred); + } + } + s->esc3_level_length= 0; + s->esc3_run_length= 0; + +s->picture_number++; //FIXME ? + + + if(w->j_type){ + ff_intrax8_decode_picture(&w->x8, 2*s->qscale, (s->qscale-1)|1 ); + return 1; + } + + return 0; +} + +static inline int wmv2_decode_motion(Wmv2Context *w, int *mx_ptr, int *my_ptr){ + MpegEncContext * const s= &w->s; + int ret; + + ret= ff_msmpeg4_decode_motion(s, mx_ptr, my_ptr); + + if(ret<0) return -1; + + if((((*mx_ptr)|(*my_ptr)) & 1) && s->mspel) + w->hshift= get_bits1(&s->gb); + else + w->hshift= 0; + +//printf("%d %d ", *mx_ptr, *my_ptr); + + return 0; +} + +static int16_t *wmv2_pred_motion(Wmv2Context *w, int *px, int *py){ + MpegEncContext * const s= &w->s; + int xy, wrap, diff, type; + int16_t *A, *B, *C, *mot_val; + + wrap = s->b8_stride; + xy = s->block_index[0]; + + mot_val = s->current_picture.motion_val[0][xy]; + + A = s->current_picture.motion_val[0][xy - 1]; + B = s->current_picture.motion_val[0][xy - wrap]; + C = s->current_picture.motion_val[0][xy + 2 - wrap]; + + if(s->mb_x && !s->first_slice_line && !s->mspel && w->top_left_mv_flag) + diff= FFMAX(FFABS(A[0] - B[0]), FFABS(A[1] - B[1])); + else + diff=0; + + if(diff >= 8) + type= get_bits1(&s->gb); + else + type= 2; + + if(type == 0){ + *px= A[0]; + *py= A[1]; + }else if(type == 1){ + *px= B[0]; + *py= B[1]; + }else{ + /* special case for first (slice) line */ + if (s->first_slice_line) { + *px = A[0]; + *py = A[1]; + } else { + *px = mid_pred(A[0], B[0], C[0]); + *py = mid_pred(A[1], B[1], C[1]); + } + } + + return mot_val; +} + +static inline int wmv2_decode_inter_block(Wmv2Context *w, DCTELEM *block, int n, int cbp){ + MpegEncContext * const s= &w->s; + static const int sub_cbp_table[3]= {2,3,1}; + int sub_cbp; + + if(!cbp){ + s->block_last_index[n] = -1; + + return 0; + } + + if(w->per_block_abt) + w->abt_type= decode012(&s->gb); +#if 0 + if(w->per_block_abt) + printf("B%d", w->abt_type); +#endif + w->abt_type_table[n]= w->abt_type; + + if(w->abt_type){ +// const uint8_t *scantable= w->abt_scantable[w->abt_type-1].permutated; + const uint8_t *scantable= w->abt_scantable[w->abt_type-1].scantable; +// const uint8_t *scantable= w->abt_type-1 ? w->abt_scantable[1].permutated : w->abt_scantable[0].scantable; + + sub_cbp= sub_cbp_table[ decode012(&s->gb) ]; +// printf("S%d", sub_cbp); + + if(sub_cbp&1){ + if (ff_msmpeg4_decode_block(s, block, n, 1, scantable) < 0) + return -1; + } + + if(sub_cbp&2){ + if (ff_msmpeg4_decode_block(s, w->abt_block2[n], n, 1, scantable) < 0) + return -1; + } + s->block_last_index[n] = 63; + + return 0; + }else{ + return ff_msmpeg4_decode_block(s, block, n, 1, s->inter_scantable.permutated); + } +} + + +int ff_wmv2_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) +{ + Wmv2Context * const w= (Wmv2Context*)s; + int cbp, code, i; + uint8_t *coded_val; + + if(w->j_type) return 0; + + if (s->pict_type == FF_P_TYPE) { + if(IS_SKIP(s->current_picture.mb_type[s->mb_y * s->mb_stride + s->mb_x])){ + /* skip mb */ + s->mb_intra = 0; + for(i=0;i<6;i++) + s->block_last_index[i] = -1; + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mv[0][0][0] = 0; + s->mv[0][0][1] = 0; + s->mb_skipped = 1; + w->hshift=0; + return 0; + } + + code = get_vlc2(&s->gb, ff_mb_non_intra_vlc[w->cbp_table_index].table, MB_NON_INTRA_VLC_BITS, 3); + if (code < 0) + return -1; + s->mb_intra = (~code & 0x40) >> 6; + + cbp = code & 0x3f; + } else { + s->mb_intra = 1; + code = get_vlc2(&s->gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); + if (code < 0){ + av_log(s->avctx, AV_LOG_ERROR, "II-cbp illegal at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + /* predict coded block pattern */ + cbp = 0; + for(i=0;i<6;i++) { + int val = ((code >> (5 - i)) & 1); + if (i < 4) { + int pred = ff_msmpeg4_coded_block_pred(s, i, &coded_val); + val = val ^ pred; + *coded_val = val; + } + cbp |= val << (5 - i); + } + } + + if (!s->mb_intra) { + int mx, my; +//printf("P at %d %d\n", s->mb_x, s->mb_y); + wmv2_pred_motion(w, &mx, &my); + + if(cbp){ + s->dsp.clear_blocks(s->block[0]); + if(s->per_mb_rl_table){ + s->rl_table_index = decode012(&s->gb); + s->rl_chroma_table_index = s->rl_table_index; + } + + if(w->abt_flag && w->per_mb_abt){ + w->per_block_abt= get_bits1(&s->gb); + if(!w->per_block_abt) + w->abt_type= decode012(&s->gb); + }else + w->per_block_abt=0; + } + + if (wmv2_decode_motion(w, &mx, &my) < 0) + return -1; + + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mv[0][0][0] = mx; + s->mv[0][0][1] = my; + + for (i = 0; i < 6; i++) { + if (wmv2_decode_inter_block(w, block[i], i, (cbp >> (5 - i)) & 1) < 0) + { + av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding inter block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); + return -1; + } + } + } else { +//if(s->pict_type==FF_P_TYPE) +// printf("%d%d ", s->inter_intra_pred, cbp); +//printf("I at %d %d %d %06X\n", s->mb_x, s->mb_y, ((cbp&3)? 1 : 0) +((cbp&0x3C)? 2 : 0), show_bits(&s->gb, 24)); + s->ac_pred = get_bits1(&s->gb); + if(s->inter_intra_pred){ + s->h263_aic_dir= get_vlc2(&s->gb, ff_inter_intra_vlc.table, INTER_INTRA_VLC_BITS, 1); +// printf("%d%d %d %d/", s->ac_pred, s->h263_aic_dir, s->mb_x, s->mb_y); + } + if(s->per_mb_rl_table && cbp){ + s->rl_table_index = decode012(&s->gb); + s->rl_chroma_table_index = s->rl_table_index; + } + + s->dsp.clear_blocks(s->block[0]); + for (i = 0; i < 6; i++) { + if (ff_msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0) + { + av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding intra block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); + return -1; + } + } + } + + return 0; +} + +static av_cold int wmv2_decode_init(AVCodecContext *avctx){ + Wmv2Context * const w= avctx->priv_data; + + if(avctx->idct_algo==FF_IDCT_AUTO){ + avctx->idct_algo=FF_IDCT_WMV2; + } + + if(ff_h263_decode_init(avctx) < 0) + return -1; + + ff_wmv2_common_init(w); + + ff_intrax8_common_init(&w->x8,&w->s); + + return 0; +} + +static av_cold int wmv2_decode_end(AVCodecContext *avctx) +{ + Wmv2Context *w = avctx->priv_data; + + ff_intrax8_common_end(&w->x8); + return ff_h263_decode_end(avctx); +} + +AVCodec wmv2_decoder = { + "wmv2", + CODEC_TYPE_VIDEO, + CODEC_ID_WMV2, + sizeof(Wmv2Context), + wmv2_decode_init, + NULL, + wmv2_decode_end, + ff_h263_decode_frame, + CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 8"), +}; diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/wmv2enc.c b/src/add-ons/media/plugins/avcodec/libavcodec/wmv2enc.c new file mode 100644 index 0000000000..a31a05a923 --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/wmv2enc.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2002 The FFmpeg Project. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "dsputil.h" +#include "mpegvideo.h" +#include "msmpeg4.h" +#include "msmpeg4data.h" +#include "wmv2.h" + + +static int encode_ext_header(Wmv2Context *w){ + MpegEncContext * const s= &w->s; + PutBitContext pb; + int code; + + init_put_bits(&pb, s->avctx->extradata, s->avctx->extradata_size); + + put_bits(&pb, 5, s->avctx->time_base.den / s->avctx->time_base.num); //yes 29.97 -> 29 + put_bits(&pb, 11, FFMIN(s->bit_rate/1024, 2047)); + + put_bits(&pb, 1, w->mspel_bit=1); + put_bits(&pb, 1, s->loop_filter); + put_bits(&pb, 1, w->abt_flag=1); + put_bits(&pb, 1, w->j_type_bit=1); + put_bits(&pb, 1, w->top_left_mv_flag=0); + put_bits(&pb, 1, w->per_mb_rl_bit=1); + put_bits(&pb, 3, code=1); + + flush_put_bits(&pb); + + s->slice_height = s->mb_height / code; + + return 0; +} + +static av_cold int wmv2_encode_init(AVCodecContext *avctx){ + Wmv2Context * const w= avctx->priv_data; + + if(MPV_encode_init(avctx) < 0) + return -1; + + ff_wmv2_common_init(w); + + avctx->extradata_size= 4; + avctx->extradata= av_mallocz(avctx->extradata_size + 10); + encode_ext_header(w); + + return 0; +} + +#if 0 /* unused, remove? */ +static av_cold int wmv2_encode_end(AVCodecContext *avctx){ + + if(MPV_encode_end(avctx) < 0) + return -1; + + avctx->extradata_size= 0; + av_freep(&avctx->extradata); + + return 0; +} +#endif + +int ff_wmv2_encode_picture_header(MpegEncContext * s, int picture_number) +{ + Wmv2Context * const w= (Wmv2Context*)s; + + put_bits(&s->pb, 1, s->pict_type - 1); + if(s->pict_type == FF_I_TYPE){ + put_bits(&s->pb, 7, 0); + } + put_bits(&s->pb, 5, s->qscale); + + s->dc_table_index = 1; + s->mv_table_index = 1; /* only if P frame */ +// s->use_skip_mb_code = 1; /* only if P frame */ + s->per_mb_rl_table = 0; + s->mspel= 0; + w->per_mb_abt=0; + w->abt_type=0; + w->j_type=0; + + assert(s->flipflop_rounding); + + if (s->pict_type == FF_I_TYPE) { + assert(s->no_rounding==1); + if(w->j_type_bit) put_bits(&s->pb, 1, w->j_type); + + if(w->per_mb_rl_bit) put_bits(&s->pb, 1, s->per_mb_rl_table); + + if(!s->per_mb_rl_table){ + ff_msmpeg4_code012(&s->pb, s->rl_chroma_table_index); + ff_msmpeg4_code012(&s->pb, s->rl_table_index); + } + + put_bits(&s->pb, 1, s->dc_table_index); + + s->inter_intra_pred= 0; + }else{ + int cbp_index; + + put_bits(&s->pb, 2, SKIP_TYPE_NONE); + + ff_msmpeg4_code012(&s->pb, cbp_index=0); + if(s->qscale <= 10){ + int map[3]= {0,2,1}; + w->cbp_table_index= map[cbp_index]; + }else if(s->qscale <= 20){ + int map[3]= {1,0,2}; + w->cbp_table_index= map[cbp_index]; + }else{ + int map[3]= {2,1,0}; + w->cbp_table_index= map[cbp_index]; + } + + if(w->mspel_bit) put_bits(&s->pb, 1, s->mspel); + + if(w->abt_flag){ + put_bits(&s->pb, 1, w->per_mb_abt^1); + if(!w->per_mb_abt){ + ff_msmpeg4_code012(&s->pb, w->abt_type); + } + } + + if(w->per_mb_rl_bit) put_bits(&s->pb, 1, s->per_mb_rl_table); + + if(!s->per_mb_rl_table){ + ff_msmpeg4_code012(&s->pb, s->rl_table_index); + s->rl_chroma_table_index = s->rl_table_index; + } + put_bits(&s->pb, 1, s->dc_table_index); + put_bits(&s->pb, 1, s->mv_table_index); + + s->inter_intra_pred= 0;//(s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE); + } + s->esc3_level_length= 0; + s->esc3_run_length= 0; + + return 0; +} + +/* Nearly identical to wmv1 but that is just because we do not use the + * useless M$ crap features. It is duplicated here in case someone wants + * to add support for these crap features. */ +void ff_wmv2_encode_mb(MpegEncContext * s, + DCTELEM block[6][64], + int motion_x, int motion_y) +{ + Wmv2Context * const w= (Wmv2Context*)s; + int cbp, coded_cbp, i; + int pred_x, pred_y; + uint8_t *coded_block; + + ff_msmpeg4_handle_slices(s); + + if (!s->mb_intra) { + /* compute cbp */ + cbp = 0; + for (i = 0; i < 6; i++) { + if (s->block_last_index[i] >= 0) + cbp |= 1 << (5 - i); + } + + put_bits(&s->pb, + wmv2_inter_table[w->cbp_table_index][cbp + 64][1], + wmv2_inter_table[w->cbp_table_index][cbp + 64][0]); + + /* motion vector */ + h263_pred_motion(s, 0, 0, &pred_x, &pred_y); + ff_msmpeg4_encode_motion(s, motion_x - pred_x, + motion_y - pred_y); + } else { + /* compute cbp */ + cbp = 0; + coded_cbp = 0; + for (i = 0; i < 6; i++) { + int val, pred; + val = (s->block_last_index[i] >= 1); + cbp |= val << (5 - i); + if (i < 4) { + /* predict value for close blocks only for luma */ + pred = ff_msmpeg4_coded_block_pred(s, i, &coded_block); + *coded_block = val; + val = val ^ pred; + } + coded_cbp |= val << (5 - i); + } +#if 0 + if (coded_cbp) + printf("cbp=%x %x\n", cbp, coded_cbp); +#endif + + if (s->pict_type == FF_I_TYPE) { + put_bits(&s->pb, + ff_msmp4_mb_i_table[coded_cbp][1], ff_msmp4_mb_i_table[coded_cbp][0]); + } else { + put_bits(&s->pb, + wmv2_inter_table[w->cbp_table_index][cbp][1], + wmv2_inter_table[w->cbp_table_index][cbp][0]); + } + put_bits(&s->pb, 1, 0); /* no AC prediction yet */ + if(s->inter_intra_pred){ + s->h263_aic_dir=0; + put_bits(&s->pb, table_inter_intra[s->h263_aic_dir][1], table_inter_intra[s->h263_aic_dir][0]); + } + } + + for (i = 0; i < 6; i++) { + ff_msmpeg4_encode_block(s, block[i], i); + } +} + +AVCodec wmv2_encoder = { + "wmv2", + CODEC_TYPE_VIDEO, + CODEC_ID_WMV2, + sizeof(Wmv2Context), + wmv2_encode_init, + MPV_encode_picture, + MPV_encode_end, + .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE}, + .long_name= NULL_IF_CONFIG_SMALL("Windows Media Video 8"), +}; diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/wnv1.c b/src/add-ons/media/plugins/avcodec/libavcodec/wnv1.c new file mode 100644 index 0000000000..70c6338037 --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/wnv1.c @@ -0,0 +1,145 @@ +/* + * Winnov WNV1 codec + * Copyright (c) 2005 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file wnv1.c + * Winnov WNV1 codec. + */ + +#include "avcodec.h" +#include "bitstream.h" + + +typedef struct WNV1Context{ + AVCodecContext *avctx; + AVFrame pic; + + int shift; + GetBitContext gb; +} WNV1Context; + +static const uint16_t code_tab[16][2]={ +{0x1FD,9}, {0xFD,8}, {0x7D,7}, {0x3D,6}, {0x1D,5}, {0x0D,4}, {0x005,3}, +{0x000,1}, +{0x004,3}, {0x0C,4}, {0x1C,5}, {0x3C,6}, {0x7C,7}, {0xFC,8}, {0x1FC,9}, {0xFF,8} +}; + +#define CODE_VLC_BITS 9 +static VLC code_vlc; + +/* returns modified base_value */ +static inline int wnv1_get_code(WNV1Context *w, int base_value) +{ + int v = get_vlc2(&w->gb, code_vlc.table, CODE_VLC_BITS, 1); + + if(v==15) + return ff_reverse[ get_bits(&w->gb, 8 - w->shift) ]; + else + return base_value + ((v - 7)<shift); +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *data_size, + uint8_t *buf, int buf_size) +{ + WNV1Context * const l = avctx->priv_data; + AVFrame * const p= (AVFrame*)&l->pic; + unsigned char *Y,*U,*V; + int i, j; + int prev_y = 0, prev_u = 0, prev_v = 0; + + if(p->data[0]) + avctx->release_buffer(avctx, p); + + p->reference = 0; + if(avctx->get_buffer(avctx, p) < 0){ + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return -1; + } + p->key_frame = 1; + + for(i=8; igb, buf+8, (buf_size-8)*8); + + if (buf[2] >> 4 == 6) + l->shift = 2; + else { + l->shift = 8 - (buf[2] >> 4); + if (l->shift > 4) { + av_log(avctx, AV_LOG_ERROR, "Unknown WNV1 frame header value %i, please upload file for study\n", buf[2] >> 4); + l->shift = 4; + } + if (l->shift < 1) { + av_log(avctx, AV_LOG_ERROR, "Unknown WNV1 frame header value %i, please upload file for study\n", buf[2] >> 4); + l->shift = 1; + } + } + + Y = p->data[0]; + U = p->data[1]; + V = p->data[2]; + for (j = 0; j < avctx->height; j++) { + for (i = 0; i < avctx->width / 2; i++) { + Y[i * 2] = wnv1_get_code(l, prev_y); + prev_u = U[i] = wnv1_get_code(l, prev_u); + prev_y = Y[(i * 2) + 1] = wnv1_get_code(l, Y[i * 2]); + prev_v = V[i] = wnv1_get_code(l, prev_v); + } + Y += p->linesize[0]; + U += p->linesize[1]; + V += p->linesize[2]; + } + + + *data_size = sizeof(AVFrame); + *(AVFrame*)data = l->pic; + + return buf_size; +} + +static av_cold int decode_init(AVCodecContext *avctx){ + WNV1Context * const l = avctx->priv_data; + + l->avctx = avctx; + avctx->pix_fmt = PIX_FMT_YUV422P; + + if(!code_vlc.table){ + init_vlc(&code_vlc, CODE_VLC_BITS, 16, + &code_tab[0][1], 4, 2, + &code_tab[0][0], 4, 2, 1); + } + + return 0; +} + +AVCodec wnv1_decoder = { + "wnv1", + CODEC_TYPE_VIDEO, + CODEC_ID_WNV1, + sizeof(WNV1Context), + decode_init, + NULL, + NULL, + decode_frame, + CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Winnov WNV1"), +}; diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/ws-snd1.c b/src/add-ons/media/plugins/avcodec/libavcodec/ws-snd1.c new file mode 100644 index 0000000000..24753b0c9c --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/ws-snd1.c @@ -0,0 +1,154 @@ +/* + * Westwood SNDx codecs + * Copyright (c) 2005 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "avcodec.h" + +/** + * @file ws-snd.c + * Westwood SNDx codecs. + * + * Reference documents about VQA format and its audio codecs + * can be found here: + * http://www.multimedia.cx + */ + +static const char ws_adpcm_2bit[] = { -2, -1, 0, 1}; +static const char ws_adpcm_4bit[] = { + -9, -8, -6, -5, -4, -3, -2, -1, + 0, 1, 2, 3, 4, 5, 6, 8 }; + +#define CLIP8(a) if(a>127)a=127;if(a<-128)a=-128; + +static av_cold int ws_snd_decode_init(AVCodecContext * avctx) +{ +// WSSNDContext *c = avctx->priv_data; + + avctx->sample_fmt = SAMPLE_FMT_S16; + return 0; +} + +static int ws_snd_decode_frame(AVCodecContext *avctx, + void *data, int *data_size, + const uint8_t *buf, int buf_size) +{ +// WSSNDContext *c = avctx->priv_data; + + int in_size, out_size; + int sample = 0; + int i; + short *samples = data; + + if (!buf_size) + return 0; + + out_size = AV_RL16(&buf[0]); + *data_size = out_size * 2; + in_size = AV_RL16(&buf[2]); + buf += 4; + + if (out_size > *data_size) { + av_log(avctx, AV_LOG_ERROR, "Frame is too large to fit in buffer\n"); + return -1; + } + if (in_size > buf_size) { + av_log(avctx, AV_LOG_ERROR, "Frame data is larger than input buffer\n"); + return -1; + } + if (in_size == out_size) { + for (i = 0; i < out_size; i++) + *samples++ = (*buf++ - 0x80) << 8; + return buf_size; + } + + while (out_size > 0) { + int code; + uint8_t count; + code = (*buf) >> 6; + count = (*buf) & 0x3F; + buf++; + switch(code) { + case 0: /* ADPCM 2-bit */ + for (count++; count > 0; count--) { + code = *buf++; + sample += ws_adpcm_2bit[code & 0x3]; + CLIP8(sample); + *samples++ = sample << 8; + sample += ws_adpcm_2bit[(code >> 2) & 0x3]; + CLIP8(sample); + *samples++ = sample << 8; + sample += ws_adpcm_2bit[(code >> 4) & 0x3]; + CLIP8(sample); + *samples++ = sample << 8; + sample += ws_adpcm_2bit[(code >> 6) & 0x3]; + CLIP8(sample); + *samples++ = sample << 8; + out_size -= 4; + } + break; + case 1: /* ADPCM 4-bit */ + for (count++; count > 0; count--) { + code = *buf++; + sample += ws_adpcm_4bit[code & 0xF]; + CLIP8(sample); + *samples++ = sample << 8; + sample += ws_adpcm_4bit[code >> 4]; + CLIP8(sample); + *samples++ = sample << 8; + out_size -= 2; + } + break; + case 2: /* no compression */ + if (count & 0x20) { /* big delta */ + char t; + t = count; + t <<= 3; + sample += t >> 3; + *samples++ = sample << 8; + out_size--; + } else { /* copy */ + for (count++; count > 0; count--) { + *samples++ = (*buf++ - 0x80) << 8; + out_size--; + } + sample = buf[-1] - 0x80; + } + break; + default: /* run */ + for(count++; count > 0; count--) { + *samples++ = sample << 8; + out_size--; + } + } + } + + return buf_size; +} + +AVCodec ws_snd1_decoder = { + "ws_snd1", + CODEC_TYPE_AUDIO, + CODEC_ID_WESTWOOD_SND1, + 0, + ws_snd_decode_init, + NULL, + NULL, + ws_snd_decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("Westwood Audio (SND1)"), +};