* PCM codecs
*/
+#include "config.h"
#include "libavutil/attributes.h"
#include "libavutil/float_dsp.h"
+#include "libavutil/thread.h"
#include "avcodec.h"
#include "bytestream.h"
#include "internal.h"
static av_cold int pcm_encode_init(AVCodecContext *avctx)
{
avctx->frame_size = 0;
+#if !CONFIG_HARDCODED_TABLES
switch (avctx->codec->id) {
- case AV_CODEC_ID_PCM_ALAW:
- pcm_alaw_tableinit();
- break;
- case AV_CODEC_ID_PCM_MULAW:
- pcm_ulaw_tableinit();
- break;
+#define INIT_ONCE(id, name) \
+ case AV_CODEC_ID_PCM_ ## id: \
+ if (CONFIG_PCM_ ## id ## _ENCODER) { \
+ static AVOnce init_static_once = AV_ONCE_INIT; \
+ ff_thread_once(&init_static_once, pcm_ ## name ## _tableinit); \
+ } \
+ break
+ INIT_ONCE(ALAW, alaw);
+ INIT_ONCE(MULAW, ulaw);
+ INIT_ONCE(VIDC, vidc);
default:
break;
}
+#endif
avctx->bits_per_coded_sample = av_get_bits_per_sample(avctx->codec->id);
avctx->block_align = avctx->channels * avctx->bits_per_coded_sample / 8;
*dst++ = linear_to_ulaw[(v + 32768) >> 2];
}
break;
+ case AV_CODEC_ID_PCM_VIDC:
+ for (; n > 0; n--) {
+ v = *samples++;
+ *dst++ = linear_to_vidc[(v + 32768) >> 2];
+ }
+ break;
default:
return -1;
}
typedef struct PCMDecode {
short table[256];
- AVFloatDSPContext *fdsp;
+ void (*vector_fmul_scalar)(float *dst, const float *src, float mul,
+ int len);
float scale;
} PCMDecode;
static av_cold int pcm_decode_init(AVCodecContext *avctx)
{
PCMDecode *s = avctx->priv_data;
+ AVFloatDSPContext *fdsp;
int i;
if (avctx->channels <= 0) {
for (i = 0; i < 256; i++)
s->table[i] = ulaw2linear(i);
break;
+ case AV_CODEC_ID_PCM_VIDC:
+ for (i = 0; i < 256; i++)
+ s->table[i] = vidc2linear(i);
+ break;
case AV_CODEC_ID_PCM_F16LE:
case AV_CODEC_ID_PCM_F24LE:
+ if (avctx->bits_per_coded_sample < 1 || avctx->bits_per_coded_sample > 24)
+ return AVERROR_INVALIDDATA;
+
s->scale = 1. / (1 << (avctx->bits_per_coded_sample - 1));
- s->fdsp = avpriv_float_dsp_alloc(0);
- if (!s->fdsp)
+ fdsp = avpriv_float_dsp_alloc(0);
+ if (!fdsp)
return AVERROR(ENOMEM);
+ s->vector_fmul_scalar = fdsp->vector_fmul_scalar;
+ av_free(fdsp);
break;
default:
break;
return 0;
}
-static av_cold int pcm_decode_close(AVCodecContext *avctx)
-{
- PCMDecode *s = avctx->priv_data;
-
- av_freep(&s->fdsp);
-
- return 0;
-}
-
/**
* Read PCM samples macro
* @param size Data size of native machine format
* @param shift Bitshift (bits)
* @param offset Sample value offset
*/
-#define DECODE(size, endian, src, dst, n, shift, offset) \
- for (; n > 0; n--) { \
- uint ## size ## _t v = bytestream_get_ ## endian(&src); \
- AV_WN ## size ## A(dst, (v - offset) << shift); \
- dst += size / 8; \
+#define DECODE(size, endian, src, dst, n, shift, offset) \
+ for (; n > 0; n--) { \
+ uint ## size ## _t v = bytestream_get_ ## endian(&src); \
+ AV_WN ## size ## A(dst, (uint ## size ## _t)(v - offset) << shift); \
+ dst += size / 8; \
}
-#define DECODE_PLANAR(size, endian, src, dst, n, shift, offset) \
- n /= avctx->channels; \
- for (c = 0; c < avctx->channels; c++) { \
- int i; \
- dst = frame->extended_data[c]; \
- for (i = n; i > 0; i--) { \
- uint ## size ## _t v = bytestream_get_ ## endian(&src); \
- AV_WN ## size ## A(dst, (v - offset) << shift); \
- dst += size / 8; \
- } \
+#define DECODE_PLANAR(size, endian, src, dst, n, shift, offset) \
+ n /= avctx->channels; \
+ for (c = 0; c < avctx->channels; c++) { \
+ int i; \
+ dst = frame->extended_data[c]; \
+ for (i = n; i > 0; i--) { \
+ uint ## size ## _t v = bytestream_get_ ## endian(&src); \
+ AV_WN ## size ## A(dst, (uint ## size ##_t)(v - offset) << shift); \
+ dst += size / 8; \
+ } \
}
static int pcm_decode_frame(AVCodecContext *avctx, void *data,
for (; n > 0; n--)
*samples++ = *src++ + 128;
break;
+ case AV_CODEC_ID_PCM_SGA:
+ for (; n > 0; n--) {
+ int sign = *src >> 7;
+ int magn = *src & 0x7f;
+ *samples++ = sign ? 128 - magn : 128 + magn;
+ src++;
+ }
+ break;
case AV_CODEC_ID_PCM_S8_PLANAR:
n /= avctx->channels;
for (c = 0; c < avctx->channels; c++) {
bytestream_get_buffer(&src, samples, n * sample_size);
}
break;
- case AV_CODEC_ID_PCM_ZORK:
- for (; n > 0; n--) {
- int v = *src++;
- if (v < 128)
- v = 128 - v;
- *samples++ = v;
- }
- break;
case AV_CODEC_ID_PCM_ALAW:
case AV_CODEC_ID_PCM_MULAW:
+ case AV_CODEC_ID_PCM_VIDC:
for (; n > 0; n--) {
AV_WN16A(samples, s->table[*src++]);
samples += 2;
dst_int32_t = (int32_t *)frame->extended_data[c];
for (i = 0; i < n; i++) {
// extract low 20 bits and expand to 32 bits
- *dst_int32_t++ = (src[2] << 28) |
+ *dst_int32_t++ = ((uint32_t)src[2]<<28) |
(src[1] << 20) |
(src[0] << 12) |
((src[2] & 0x0F) << 8) |
src[1];
// extract high 20 bits and expand to 32 bits
- *dst_int32_t++ = (src[4] << 24) |
+ *dst_int32_t++ = ((uint32_t)src[4]<<24) |
(src[3] << 16) |
((src[2] & 0xF0) << 8) |
(src[4] << 4) |
if (avctx->codec_id == AV_CODEC_ID_PCM_F16LE ||
avctx->codec_id == AV_CODEC_ID_PCM_F24LE) {
- s->fdsp->vector_fmul_scalar((float *)frame->extended_data[0],
- (const float *)frame->extended_data[0],
- s->scale, FFALIGN(frame->nb_samples * avctx->channels, 4));
+ s->vector_fmul_scalar((float *)frame->extended_data[0],
+ (const float *)frame->extended_data[0],
+ s->scale, FFALIGN(frame->nb_samples * avctx->channels, 4));
emms_c();
}
.capabilities = AV_CODEC_CAP_VARIABLE_FRAME_SIZE, \
.sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_, \
AV_SAMPLE_FMT_NONE }, \
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \
}
#define PCM_ENCODER_2(cf, id, sample_fmt, name, long_name) \
.id = AV_CODEC_ID_ ## id_, \
.priv_data_size = sizeof(PCMDecode), \
.init = pcm_decode_init, \
- .close = pcm_decode_close, \
.decode = pcm_decode_frame, \
.capabilities = AV_CODEC_CAP_DR1, \
.sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_, \
AV_SAMPLE_FMT_NONE }, \
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \
}
#define PCM_DECODER_2(cf, id, sample_fmt, name, long_name) \
PCM_CODEC (PCM_U24LE, AV_SAMPLE_FMT_S32, pcm_u24le, "PCM unsigned 24-bit little-endian");
PCM_CODEC (PCM_U32BE, AV_SAMPLE_FMT_S32, pcm_u32be, "PCM unsigned 32-bit big-endian");
PCM_CODEC (PCM_U32LE, AV_SAMPLE_FMT_S32, pcm_u32le, "PCM unsigned 32-bit little-endian");
-PCM_DECODER(PCM_ZORK, AV_SAMPLE_FMT_U8, pcm_zork, "PCM Zork");
PCM_CODEC (PCM_S64BE, AV_SAMPLE_FMT_S64, pcm_s64be, "PCM signed 64-bit big-endian");
PCM_CODEC (PCM_S64LE, AV_SAMPLE_FMT_S64, pcm_s64le, "PCM signed 64-bit little-endian");
+PCM_CODEC (PCM_VIDC, AV_SAMPLE_FMT_S16, pcm_vidc, "PCM Archimedes VIDC");
+PCM_DECODER(PCM_SGA, AV_SAMPLE_FMT_U8, pcm_sga, "PCM SGA");