#include "libavutil/avassert.h"
#include "libavutil/intreadwrite.h"
+#include "libavutil/mem_internal.h"
#include "internal.h"
#include "get_bits.h"
#include "avcodec.h"
#define DST_MAX_CHANNELS 6
#define DST_MAX_ELEMENTS (2 * DST_MAX_CHANNELS)
-#define DSD_FS44(sample_rate) (sample_rate * 8 / 44100)
+#define DSD_FS44(sample_rate) (sample_rate * 8LL / 44100)
#define DST_SAMPLES_PER_FRAME(sample_rate) (588 * DSD_FS44(sample_rate))
GetBitContext gb;
ArithCoder ac;
Table fsets, probs;
- DECLARE_ALIGNED(64, uint8_t, status)[DST_MAX_CHANNELS][16];
+ DECLARE_ALIGNED(16, uint8_t, status)[DST_MAX_CHANNELS][16];
DECLARE_ALIGNED(16, int16_t, filter)[DST_MAX_ELEMENTS][16][256];
DSDContext dsdctx[DST_MAX_CHANNELS];
} DSTContext;
return AVERROR_PATCHWELCOME;
}
+ // the sample rate is only allowed to be 64,128,256 * 44100 by ISO/IEC 14496-3:2005(E)
+ // We are a bit more tolerant here, but this check is needed to bound the size and duration
+ if (avctx->sample_rate > 512 * 44100)
+ return AVERROR_INVALIDDATA;
+
+
+ if (DST_SAMPLES_PER_FRAME(avctx->sample_rate) & 7) {
+ return AVERROR_PATCHWELCOME;
+ }
+
avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
for (i = 0; i < avctx->channels; i++)
static av_always_inline int get_sr_golomb_dst(GetBitContext *gb, unsigned int k)
{
- int v = get_ur_golomb(gb, k, get_bits_left(gb), 0);
+ int v = get_ur_golomb_jpegls(gb, k, get_bits_left(gb), 0);
if (v && get_bits1(gb))
v = -v;
return v;
for (j = method + 1; j < t->length[i]; j++) {
int c, x = 0;
for (k = 0; k < method + 1; k++)
- x += code_pred_coeff[method][k] * t->coeff[i][j - k - 1];
+ x += code_pred_coeff[method][k] * (unsigned)t->coeff[i][j - k - 1];
c = get_sr_golomb_dst(gb, lsb_size);
if (x >= 0)
c -= (x + 4) / 8;
else
c += (-x + 3) / 8;
+ if (!is_signed) {
+ if (c < offset || c >= offset + (1<<coeff_bits))
+ return AVERROR_INVALIDDATA;
+ }
t->coeff[i][j] = c;
}
}
skip_bits1(gb);
if (get_bits(gb, 6))
return AVERROR_INVALIDDATA;
- memcpy(frame->data[0], avpkt->data + 1, FFMIN(avpkt->size - 1, frame->nb_samples * avctx->channels));
+ memcpy(frame->data[0], avpkt->data + 1, FFMIN(avpkt->size - 1, frame->nb_samples * channels));
goto dsd;
}
same_map = get_bits1(gb);
- if ((ret = read_map(gb, &s->fsets, map_ch_to_felem, avctx->channels)) < 0)
+ if ((ret = read_map(gb, &s->fsets, map_ch_to_felem, channels)) < 0)
return ret;
if (same_map) {
memcpy(map_ch_to_pelem, map_ch_to_felem, sizeof(map_ch_to_felem));
} else {
avpriv_request_sample(avctx, "Not Same Mapping");
- if ((ret = read_map(gb, &s->probs, map_ch_to_pelem, avctx->channels)) < 0)
+ if ((ret = read_map(gb, &s->probs, map_ch_to_pelem, channels)) < 0)
return ret;
}
/* Half Probability (10.10) */
- for (ch = 0; ch < avctx->channels; ch++)
+ for (ch = 0; ch < channels; ch++)
half_prob[ch] = get_bits1(gb);
/* Filter Coef Sets (10.12) */
- read_table(gb, &s->fsets, fsets_code_pred_coeff, 7, 9, 1, 0);
+ ret = read_table(gb, &s->fsets, fsets_code_pred_coeff, 7, 9, 1, 0);
+ if (ret < 0)
+ return ret;
/* Probability Tables (10.13) */
- read_table(gb, &s->probs, probs_code_pred_coeff, 6, 7, 0, 1);
+ ret = read_table(gb, &s->probs, probs_code_pred_coeff, 6, 7, 0, 1);
+ if (ret < 0)
+ return ret;
/* Arithmetic Coded Data (10.11) */
build_filter(s->filter, &s->fsets);
memset(s->status, 0xAA, sizeof(s->status));
- memset(dsd, 0, frame->nb_samples * 4 * avctx->channels);
+ memset(dsd, 0, frame->nb_samples * 4 * channels);
ac_get(ac, gb, prob_dst_x_bit(s->fsets.coeff[0][0]), &dst_x_bit);
v = ((predict >> 15) ^ residual) & 1;
dsd[((i >> 3) * channels + ch) << 2] |= v << (7 - (i & 0x7 ));
- AV_WN64A(status + 8, (AV_RN64A(status + 8) << 1) | ((AV_RN64A(status) >> 63) & 1));
- AV_WN64A(status, (AV_RN64A(status) << 1) | v);
+ AV_WL64A(status + 8, (AV_RL64A(status + 8) << 1) | ((AV_RL64A(status) >> 63) & 1));
+ AV_WL64A(status, (AV_RL64A(status) << 1) | v);
}
}
dsd:
- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < channels; i++) {
ff_dsd2pcm_translate(&s->dsdctx[i], frame->nb_samples, 0,
frame->data[0] + i * 4,
- avctx->channels * 4, pcm + i, avctx->channels);
+ channels * 4, pcm + i, channels);
}
*got_frame_ptr = 1;
return avpkt->size;
}
-AVCodec ff_dst_decoder = {
+const AVCodec ff_dst_decoder = {
.name = "dst",
.long_name = NULL_IF_CONFIG_SMALL("DST (Digital Stream Transfer)"),
.type = AVMEDIA_TYPE_AUDIO,
.capabilities = AV_CODEC_CAP_DR1,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT,
AV_SAMPLE_FMT_NONE },
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
};