X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=libavcodec%2Fpcm.c;h=79b33b935cb1d37684288a40fc8cc738976d93a1;hb=a247ac640df3da573cd661065bf53f37863e2b46;hp=ffcbccc77db58a7082856ad95dcaa3b04a91d824;hpb=ebdc5c419aef0d9eed8c1ec57b30238194c1db0a;p=ffmpeg diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c index ffcbccc77db..79b33b935cb 100644 --- a/libavcodec/pcm.c +++ b/libavcodec/pcm.c @@ -24,8 +24,10 @@ * 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" @@ -35,19 +37,22 @@ 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; - case AV_CODEC_ID_PCM_VIDC: - pcm_vidc_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; @@ -235,13 +240,15 @@ static int pcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, 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) { @@ -264,10 +271,15 @@ static av_cold int pcm_decode_init(AVCodecContext *avctx) 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; @@ -281,15 +293,6 @@ static av_cold int pcm_decode_init(AVCodecContext *avctx) 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 @@ -300,23 +303,23 @@ static av_cold int pcm_decode_close(AVCodecContext *avctx) * @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, @@ -416,6 +419,14 @@ 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++) { @@ -488,14 +499,6 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data, 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: @@ -512,13 +515,13 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data, 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) | @@ -534,9 +537,9 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data, 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(); } @@ -547,7 +550,7 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data, #define PCM_ENCODER_0(id_, sample_fmt_, name_, long_name_) #define PCM_ENCODER_1(id_, sample_fmt_, name_, long_name_) \ -AVCodec ff_ ## name_ ## _encoder = { \ +const AVCodec ff_ ## name_ ## _encoder = { \ .name = #name_, \ .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ .type = AVMEDIA_TYPE_AUDIO, \ @@ -557,6 +560,7 @@ AVCodec ff_ ## name_ ## _encoder = { \ .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) \ @@ -568,18 +572,18 @@ AVCodec ff_ ## name_ ## _encoder = { \ #define PCM_DECODER_0(id, sample_fmt, name, long_name) #define PCM_DECODER_1(id_, sample_fmt_, name_, long_name_) \ -AVCodec ff_ ## name_ ## _decoder = { \ +const AVCodec ff_ ## name_ ## _decoder = { \ .name = #name_, \ .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ .type = AVMEDIA_TYPE_AUDIO, \ .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) \ @@ -623,7 +627,7 @@ PCM_CODEC (PCM_U24BE, AV_SAMPLE_FMT_S32, pcm_u24be, "PCM unsigned 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");