1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * LucasArts VIMA decoder
3cabdff1aSopenharmony_ci * Copyright (c) 2012 Paul B Mahol
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci/**
23cabdff1aSopenharmony_ci * @file
24cabdff1aSopenharmony_ci * LucasArts VIMA audio decoder
25cabdff1aSopenharmony_ci * @author Paul B Mahol
26cabdff1aSopenharmony_ci */
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h"
29cabdff1aSopenharmony_ci#include "libavutil/thread.h"
30cabdff1aSopenharmony_ci
31cabdff1aSopenharmony_ci#include "adpcm_data.h"
32cabdff1aSopenharmony_ci#include "avcodec.h"
33cabdff1aSopenharmony_ci#include "codec_internal.h"
34cabdff1aSopenharmony_ci#include "get_bits.h"
35cabdff1aSopenharmony_ci#include "internal.h"
36cabdff1aSopenharmony_ci
37cabdff1aSopenharmony_cistatic uint16_t predict_table[5786 * 2];
38cabdff1aSopenharmony_ci
39cabdff1aSopenharmony_cistatic const uint8_t size_table[] = {
40cabdff1aSopenharmony_ci    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
41cabdff1aSopenharmony_ci    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
42cabdff1aSopenharmony_ci    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
43cabdff1aSopenharmony_ci    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
44cabdff1aSopenharmony_ci    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
45cabdff1aSopenharmony_ci    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
46cabdff1aSopenharmony_ci};
47cabdff1aSopenharmony_ci
48cabdff1aSopenharmony_cistatic const int8_t index_table1[] = {
49cabdff1aSopenharmony_ci    -1, 4, -1, 4
50cabdff1aSopenharmony_ci};
51cabdff1aSopenharmony_ci
52cabdff1aSopenharmony_cistatic const int8_t index_table2[] = {
53cabdff1aSopenharmony_ci    -1, -1, 2, 6, -1, -1, 2, 6
54cabdff1aSopenharmony_ci};
55cabdff1aSopenharmony_ci
56cabdff1aSopenharmony_cistatic const int8_t index_table3[] = {
57cabdff1aSopenharmony_ci    -1, -1, -1, -1, 1, 2, 4, 6, -1, -1, -1, -1, 1, 2, 4, 6
58cabdff1aSopenharmony_ci};
59cabdff1aSopenharmony_ci
60cabdff1aSopenharmony_cistatic const int8_t index_table4[] = {
61cabdff1aSopenharmony_ci    -1, -1, -1, -1, -1, -1, -1, -1, 1,  1,  1,  2,  2,  4,  5,  6,
62cabdff1aSopenharmony_ci    -1, -1, -1, -1, -1, -1, -1, -1, 1,  1,  1,  2,  2,  4,  5,  6
63cabdff1aSopenharmony_ci};
64cabdff1aSopenharmony_ci
65cabdff1aSopenharmony_cistatic const int8_t index_table5[] = {
66cabdff1aSopenharmony_ci    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
67cabdff1aSopenharmony_ci     1,  1,  1,  1,  1,  2,  2,  2,  2,  4,  4,  4,  5,  5,  6,  6,
68cabdff1aSopenharmony_ci    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
69cabdff1aSopenharmony_ci     1,  1,  1,  1,  1,  2,  2,  2,  2,  4,  4,  4,  5,  5,  6,  6
70cabdff1aSopenharmony_ci};
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_cistatic const int8_t index_table6[] = {
73cabdff1aSopenharmony_ci    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
74cabdff1aSopenharmony_ci    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
75cabdff1aSopenharmony_ci     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,
76cabdff1aSopenharmony_ci     2,  2,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,  6,  6,  6,  6,
77cabdff1aSopenharmony_ci    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
78cabdff1aSopenharmony_ci    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
79cabdff1aSopenharmony_ci     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,
80cabdff1aSopenharmony_ci     2,  2,  4,  4,  4,  4,  4,  4,  5,  5,  5,  5,  6,  6,  6,  6
81cabdff1aSopenharmony_ci};
82cabdff1aSopenharmony_ci
83cabdff1aSopenharmony_cistatic const int8_t *const step_index_tables[] = {
84cabdff1aSopenharmony_ci    index_table1, index_table2, index_table3,
85cabdff1aSopenharmony_ci    index_table4, index_table5, index_table6
86cabdff1aSopenharmony_ci};
87cabdff1aSopenharmony_ci
88cabdff1aSopenharmony_cistatic av_cold void predict_table_init(void)
89cabdff1aSopenharmony_ci{
90cabdff1aSopenharmony_ci    for (int start_pos = 0; start_pos < 64; start_pos++) {
91cabdff1aSopenharmony_ci        unsigned int dest_pos, table_pos;
92cabdff1aSopenharmony_ci
93cabdff1aSopenharmony_ci        for (table_pos = 0, dest_pos = start_pos;
94cabdff1aSopenharmony_ci             table_pos < FF_ARRAY_ELEMS(ff_adpcm_step_table);
95cabdff1aSopenharmony_ci             table_pos++, dest_pos += 64) {
96cabdff1aSopenharmony_ci            int put = 0, count, table_value;
97cabdff1aSopenharmony_ci
98cabdff1aSopenharmony_ci            table_value = ff_adpcm_step_table[table_pos];
99cabdff1aSopenharmony_ci            for (count = 32; count != 0; count >>= 1) {
100cabdff1aSopenharmony_ci                if (start_pos & count)
101cabdff1aSopenharmony_ci                    put += table_value;
102cabdff1aSopenharmony_ci                table_value >>= 1;
103cabdff1aSopenharmony_ci            }
104cabdff1aSopenharmony_ci            predict_table[dest_pos] = put;
105cabdff1aSopenharmony_ci        }
106cabdff1aSopenharmony_ci    }
107cabdff1aSopenharmony_ci}
108cabdff1aSopenharmony_ci
109cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext *avctx)
110cabdff1aSopenharmony_ci{
111cabdff1aSopenharmony_ci    static AVOnce init_static_once = AV_ONCE_INIT;
112cabdff1aSopenharmony_ci
113cabdff1aSopenharmony_ci    avctx->sample_fmt = AV_SAMPLE_FMT_S16;
114cabdff1aSopenharmony_ci
115cabdff1aSopenharmony_ci    ff_thread_once(&init_static_once, predict_table_init);
116cabdff1aSopenharmony_ci
117cabdff1aSopenharmony_ci    return 0;
118cabdff1aSopenharmony_ci}
119cabdff1aSopenharmony_ci
120cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *frame,
121cabdff1aSopenharmony_ci                        int *got_frame_ptr, AVPacket *pkt)
122cabdff1aSopenharmony_ci{
123cabdff1aSopenharmony_ci    GetBitContext gb;
124cabdff1aSopenharmony_ci    int16_t pcm_data[2];
125cabdff1aSopenharmony_ci    uint32_t samples;
126cabdff1aSopenharmony_ci    int8_t channel_hint[2];
127cabdff1aSopenharmony_ci    int ret, chan;
128cabdff1aSopenharmony_ci    int channels = 1;
129cabdff1aSopenharmony_ci
130cabdff1aSopenharmony_ci    if (pkt->size < 13)
131cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
132cabdff1aSopenharmony_ci
133cabdff1aSopenharmony_ci    if ((ret = init_get_bits8(&gb, pkt->data, pkt->size)) < 0)
134cabdff1aSopenharmony_ci        return ret;
135cabdff1aSopenharmony_ci
136cabdff1aSopenharmony_ci    samples = get_bits_long(&gb, 32);
137cabdff1aSopenharmony_ci    if (samples == 0xffffffff) {
138cabdff1aSopenharmony_ci        skip_bits_long(&gb, 32);
139cabdff1aSopenharmony_ci        samples = get_bits_long(&gb, 32);
140cabdff1aSopenharmony_ci    }
141cabdff1aSopenharmony_ci
142cabdff1aSopenharmony_ci    if (samples > pkt->size * 2)
143cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
144cabdff1aSopenharmony_ci
145cabdff1aSopenharmony_ci    channel_hint[0] = get_sbits(&gb, 8);
146cabdff1aSopenharmony_ci    if (channel_hint[0] & 0x80) {
147cabdff1aSopenharmony_ci        channel_hint[0] = ~channel_hint[0];
148cabdff1aSopenharmony_ci        channels = 2;
149cabdff1aSopenharmony_ci    }
150cabdff1aSopenharmony_ci    av_channel_layout_uninit(&avctx->ch_layout);
151cabdff1aSopenharmony_ci    av_channel_layout_default(&avctx->ch_layout, channels);
152cabdff1aSopenharmony_ci    pcm_data[0] = get_sbits(&gb, 16);
153cabdff1aSopenharmony_ci    if (channels > 1) {
154cabdff1aSopenharmony_ci        channel_hint[1] = get_sbits(&gb, 8);
155cabdff1aSopenharmony_ci        pcm_data[1]     = get_sbits(&gb, 16);
156cabdff1aSopenharmony_ci    }
157cabdff1aSopenharmony_ci
158cabdff1aSopenharmony_ci    frame->nb_samples = samples;
159cabdff1aSopenharmony_ci    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
160cabdff1aSopenharmony_ci        return ret;
161cabdff1aSopenharmony_ci
162cabdff1aSopenharmony_ci    for (chan = 0; chan < channels; chan++) {
163cabdff1aSopenharmony_ci        uint16_t *dest = (uint16_t *)frame->data[0] + chan;
164cabdff1aSopenharmony_ci        int step_index = channel_hint[chan];
165cabdff1aSopenharmony_ci        int output = pcm_data[chan];
166cabdff1aSopenharmony_ci        int sample;
167cabdff1aSopenharmony_ci
168cabdff1aSopenharmony_ci        for (sample = 0; sample < samples; sample++) {
169cabdff1aSopenharmony_ci            int lookup_size, lookup, highbit, lowbits;
170cabdff1aSopenharmony_ci
171cabdff1aSopenharmony_ci            step_index  = av_clip(step_index, 0, 88);
172cabdff1aSopenharmony_ci            lookup_size = size_table[step_index];
173cabdff1aSopenharmony_ci            lookup      = get_bits(&gb, lookup_size);
174cabdff1aSopenharmony_ci            highbit     = 1 << (lookup_size - 1);
175cabdff1aSopenharmony_ci            lowbits     = highbit - 1;
176cabdff1aSopenharmony_ci
177cabdff1aSopenharmony_ci            if (lookup & highbit)
178cabdff1aSopenharmony_ci                lookup ^= highbit;
179cabdff1aSopenharmony_ci            else
180cabdff1aSopenharmony_ci                highbit = 0;
181cabdff1aSopenharmony_ci
182cabdff1aSopenharmony_ci            if (lookup == lowbits) {
183cabdff1aSopenharmony_ci                output = get_sbits(&gb, 16);
184cabdff1aSopenharmony_ci            } else {
185cabdff1aSopenharmony_ci                int predict_index, diff;
186cabdff1aSopenharmony_ci
187cabdff1aSopenharmony_ci                predict_index = (lookup << (7 - lookup_size)) | (step_index << 6);
188cabdff1aSopenharmony_ci                predict_index = av_clip(predict_index, 0, 5785);
189cabdff1aSopenharmony_ci                diff          = predict_table[predict_index];
190cabdff1aSopenharmony_ci                if (lookup)
191cabdff1aSopenharmony_ci                    diff += ff_adpcm_step_table[step_index] >> (lookup_size - 1);
192cabdff1aSopenharmony_ci                if (highbit)
193cabdff1aSopenharmony_ci                    diff = -diff;
194cabdff1aSopenharmony_ci
195cabdff1aSopenharmony_ci                output = av_clip_int16(output + diff);
196cabdff1aSopenharmony_ci            }
197cabdff1aSopenharmony_ci
198cabdff1aSopenharmony_ci            *dest = output;
199cabdff1aSopenharmony_ci            dest += channels;
200cabdff1aSopenharmony_ci
201cabdff1aSopenharmony_ci            step_index += step_index_tables[lookup_size - 2][lookup];
202cabdff1aSopenharmony_ci        }
203cabdff1aSopenharmony_ci    }
204cabdff1aSopenharmony_ci
205cabdff1aSopenharmony_ci    *got_frame_ptr = 1;
206cabdff1aSopenharmony_ci
207cabdff1aSopenharmony_ci    return pkt->size;
208cabdff1aSopenharmony_ci}
209cabdff1aSopenharmony_ci
210cabdff1aSopenharmony_ciconst FFCodec ff_adpcm_vima_decoder = {
211cabdff1aSopenharmony_ci    .p.name       = "adpcm_vima",
212cabdff1aSopenharmony_ci    .p.long_name  = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"),
213cabdff1aSopenharmony_ci    .p.type       = AVMEDIA_TYPE_AUDIO,
214cabdff1aSopenharmony_ci    .p.id         = AV_CODEC_ID_ADPCM_VIMA,
215cabdff1aSopenharmony_ci    .init         = decode_init,
216cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(decode_frame),
217cabdff1aSopenharmony_ci    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
218cabdff1aSopenharmony_ci    .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
219cabdff1aSopenharmony_ci};
220