00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/audioconvert.h"
00023 #include "avcodec.h"
00024 #include "get_bits.h"
00025 #include "adpcm_data.h"
00026
00027 typedef struct {
00028 AVFrame frame;
00029 uint16_t predict_table[5786 * 2];
00030 } VimaContext;
00031
00032 static const uint8_t size_table[] =
00033 {
00034 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
00035 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
00036 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
00037 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
00038 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
00039 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
00040 };
00041
00042 static const int8_t index_table1[] =
00043 {
00044 -1, 4, -1, 4
00045 };
00046
00047 static const int8_t index_table2[] =
00048 {
00049 -1, -1, 2, 6, -1, -1, 2, 6
00050 };
00051
00052 static const int8_t index_table3[] =
00053 {
00054 -1, -1, -1, -1, 1, 2, 4, 6,
00055 -1, -1, -1, -1, 1, 2, 4, 6
00056 };
00057
00058 static const int8_t index_table4[] =
00059 {
00060 -1, -1, -1, -1, -1, -1, -1, -1,
00061 1, 1, 1, 2, 2, 4, 5, 6,
00062 -1, -1, -1, -1, -1, -1, -1, -1,
00063 1, 1, 1, 2, 2, 4, 5, 6
00064 };
00065
00066 static const int8_t index_table5[] =
00067 {
00068 -1, -1, -1, -1, -1, -1, -1, -1,
00069 -1, -1, -1, -1, -1, -1, -1, -1,
00070 1, 1, 1, 1, 1, 2, 2, 2,
00071 2, 4, 4, 4, 5, 5, 6, 6,
00072 -1, -1, -1, -1, -1, -1, -1, -1,
00073 -1, -1, -1, -1, -1, -1, -1, -1,
00074 1, 1, 1, 1, 1, 2, 2, 2,
00075 2, 4, 4, 4, 5, 5, 6, 6
00076 };
00077
00078 static const int8_t index_table6[] =
00079 {
00080 -1, -1, -1, -1, -1, -1, -1, -1,
00081 -1, -1, -1, -1, -1, -1, -1, -1,
00082 -1, -1, -1, -1, -1, -1, -1, -1,
00083 -1, -1, -1, -1, -1, -1, -1, -1,
00084 1, 1, 1, 1, 1, 1, 1, 1,
00085 1, 1, 2, 2, 2, 2, 2, 2,
00086 2, 2, 4, 4, 4, 4, 4, 4,
00087 5, 5, 5, 5, 6, 6, 6, 6,
00088 -1, -1, -1, -1, -1, -1, -1, -1,
00089 -1, -1, -1, -1, -1, -1, -1, -1,
00090 -1, -1, -1, -1, -1, -1, -1, -1,
00091 -1, -1, -1, -1, -1, -1, -1, -1,
00092 1, 1, 1, 1, 1, 1, 1, 1,
00093 1, 1, 2, 2, 2, 2, 2, 2,
00094 2, 2, 4, 4, 4, 4, 4, 4,
00095 5, 5, 5, 5, 6, 6, 6, 6
00096 };
00097
00098 static const int8_t* const step_index_tables[] =
00099 {
00100 index_table1, index_table2, index_table3,
00101 index_table4, index_table5, index_table6
00102 };
00103
00104 static av_cold int decode_init(AVCodecContext *avctx)
00105 {
00106 VimaContext *vima = avctx->priv_data;
00107 int start_pos;
00108
00109 for (start_pos = 0; start_pos < 64; start_pos++) {
00110 unsigned int dest_pos, table_pos;
00111
00112 for (table_pos = 0, dest_pos = start_pos;
00113 table_pos < FF_ARRAY_ELEMS(ff_adpcm_step_table);
00114 table_pos++, dest_pos += 64) {
00115 int put = 0, count, table_value;
00116
00117 table_value = ff_adpcm_step_table[table_pos];
00118 for (count = 32; count != 0; count >>= 1) {
00119 if (start_pos & count)
00120 put += table_value;
00121 table_value >>= 1;
00122 }
00123 vima->predict_table[dest_pos] = put;
00124 }
00125 }
00126
00127 avcodec_get_frame_defaults(&vima->frame);
00128 avctx->coded_frame = &vima->frame;
00129 avctx->sample_fmt = AV_SAMPLE_FMT_S16;
00130
00131 return 0;
00132 }
00133
00134 static int decode_frame(AVCodecContext *avctx, void *data,
00135 int *got_frame_ptr, AVPacket *pkt)
00136 {
00137 GetBitContext gb;
00138 VimaContext *vima = avctx->priv_data;
00139 int16_t pcm_data[2];
00140 uint32_t samples;
00141 int8_t channel_hint[2];
00142 int ret, chan, channels = 1;
00143
00144 init_get_bits(&gb, pkt->data, pkt->size * 8);
00145
00146 if (pkt->size < 13)
00147 return AVERROR_INVALIDDATA;
00148
00149 samples = get_bits_long(&gb, 32);
00150 if (samples == 0xffffffff) {
00151 skip_bits_long(&gb, 32);
00152 samples = get_bits_long(&gb, 32);
00153 }
00154
00155 if (samples > pkt->size * 2)
00156 return AVERROR_INVALIDDATA;
00157
00158 channel_hint[0] = get_sbits(&gb, 8);
00159 if (channel_hint[0] & 0x80) {
00160 channel_hint[0] = ~channel_hint[0];
00161 channels = 2;
00162 }
00163 avctx->channels = channels;
00164 avctx->channel_layout = (channels == 2) ? AV_CH_LAYOUT_STEREO :
00165 AV_CH_LAYOUT_MONO;
00166 pcm_data[0] = get_sbits(&gb, 16);
00167 if (channels > 1) {
00168 channel_hint[1] = get_sbits(&gb, 8);
00169 pcm_data[1] = get_sbits(&gb, 16);
00170 }
00171
00172 vima->frame.nb_samples = samples;
00173 if ((ret = avctx->get_buffer(avctx, &vima->frame)) < 0) {
00174 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00175 return ret;
00176 }
00177
00178 for (chan = 0; chan < channels; chan++) {
00179 uint16_t *dest = (uint16_t*)vima->frame.data[0] + chan;
00180 int step_index = channel_hint[chan];
00181 int output = pcm_data[chan];
00182 int sample;
00183
00184 for (sample = 0; sample < samples; sample++) {
00185 int lookup_size, lookup, highbit, lowbits;
00186
00187 step_index = av_clip(step_index, 0, 88);
00188 lookup_size = size_table[step_index];
00189 lookup = get_bits(&gb, lookup_size);
00190 highbit = 1 << (lookup_size - 1);
00191 lowbits = highbit - 1;
00192
00193 if (lookup & highbit)
00194 lookup ^= highbit;
00195 else
00196 highbit = 0;
00197
00198 if (lookup == lowbits) {
00199 output = get_sbits(&gb, 16);
00200 } else {
00201 int predict_index, diff;
00202
00203 predict_index = (lookup << (7 - lookup_size)) | (step_index << 6);
00204 predict_index = av_clip(predict_index, 0, 5785);
00205 diff = vima->predict_table[predict_index];
00206 if (lookup)
00207 diff += ff_adpcm_step_table[step_index] >> (lookup_size - 1);
00208 if (highbit)
00209 diff = -diff;
00210
00211 output = av_clip_int16(output + diff);
00212 }
00213
00214 *dest = output;
00215 dest += channels;
00216
00217 step_index += step_index_tables[lookup_size - 2][lookup];
00218 }
00219 }
00220
00221 *got_frame_ptr = 1;
00222 *(AVFrame *)data = vima->frame;
00223
00224 return pkt->size;
00225 }
00226
00227 AVCodec ff_vima_decoder = {
00228 .name = "vima",
00229 .type = AVMEDIA_TYPE_AUDIO,
00230 .id = AV_CODEC_ID_VIMA,
00231 .priv_data_size = sizeof(VimaContext),
00232 .init = decode_init,
00233 .decode = decode_frame,
00234 .capabilities = CODEC_CAP_DR1,
00235 .long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"),
00236 };