/* * PCM codecs * Copyright (c) 2001 Fabrice Bellard * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
if ((ret = ff_get_encode_buffer(avctx, avpkt, n * sample_size, 0)) < 0) return ret;
dst = avpkt->data;
switch (avctx->codec->id) { case AV_CODEC_ID_PCM_U32LE:
ENCODE(uint32_t, le32, samples, dst, n, 0, 0x80000000) break; case AV_CODEC_ID_PCM_U32BE:
ENCODE(uint32_t, be32, samples, dst, n, 0, 0x80000000) break; case AV_CODEC_ID_PCM_S24LE:
ENCODE(int32_t, le24, samples, dst, n, 8, 0) break; case AV_CODEC_ID_PCM_S24LE_PLANAR:
ENCODE_PLANAR(int32_t, le24, dst, n, 8, 0) break; case AV_CODEC_ID_PCM_S24BE:
ENCODE(int32_t, be24, samples, dst, n, 8, 0) break; case AV_CODEC_ID_PCM_U24LE:
ENCODE(uint32_t, le24, samples, dst, n, 8, 0x800000) break; case AV_CODEC_ID_PCM_U24BE:
ENCODE(uint32_t, be24, samples, dst, n, 8, 0x800000) break; case AV_CODEC_ID_PCM_S24DAUD: for (; n > 0; n--) {
uint32_t tmp = ff_reverse[(*samples >> 8) & 0xff] +
(ff_reverse[*samples & 0xff] << 8);
tmp <<= 4; // sync flags would go here
bytestream_put_be24(&dst, tmp);
samples++;
} break; case AV_CODEC_ID_PCM_U16LE:
ENCODE(uint16_t, le16, samples, dst, n, 0, 0x8000) break; case AV_CODEC_ID_PCM_U16BE:
ENCODE(uint16_t, be16, samples, dst, n, 0, 0x8000) break; case AV_CODEC_ID_PCM_S8:
ENCODE(uint8_t, byte, samples, dst, n, 0, -128) break; case AV_CODEC_ID_PCM_S8_PLANAR:
ENCODE_PLANAR(uint8_t, byte, dst, n, 0, -128) break; #if HAVE_BIGENDIAN case AV_CODEC_ID_PCM_S64LE: case AV_CODEC_ID_PCM_F64LE:
ENCODE(int64_t, le64, samples, dst, n, 0, 0) break; case AV_CODEC_ID_PCM_S32LE: case AV_CODEC_ID_PCM_F32LE:
ENCODE(int32_t, le32, samples, dst, n, 0, 0) break; case AV_CODEC_ID_PCM_S32LE_PLANAR:
ENCODE_PLANAR(int32_t, le32, dst, n, 0, 0) break; case AV_CODEC_ID_PCM_S16LE:
ENCODE(int16_t, le16, samples, dst, n, 0, 0) break; case AV_CODEC_ID_PCM_S16LE_PLANAR:
ENCODE_PLANAR(int16_t, le16, dst, n, 0, 0) break; case AV_CODEC_ID_PCM_F64BE: case AV_CODEC_ID_PCM_F32BE: case AV_CODEC_ID_PCM_S64BE: case AV_CODEC_ID_PCM_S32BE: case AV_CODEC_ID_PCM_S16BE: #else case AV_CODEC_ID_PCM_S64BE: case AV_CODEC_ID_PCM_F64BE:
ENCODE(int64_t, be64, samples, dst, n, 0, 0) break; case AV_CODEC_ID_PCM_F32BE: case AV_CODEC_ID_PCM_S32BE:
ENCODE(int32_t, be32, samples, dst, n, 0, 0) break; case AV_CODEC_ID_PCM_S16BE:
ENCODE(int16_t, be16, samples, dst, n, 0, 0) break; case AV_CODEC_ID_PCM_S16BE_PLANAR:
ENCODE_PLANAR(int16_t, be16, dst, n, 0, 0) break; case AV_CODEC_ID_PCM_F64LE: case AV_CODEC_ID_PCM_F32LE: case AV_CODEC_ID_PCM_S64LE: case AV_CODEC_ID_PCM_S32LE: case AV_CODEC_ID_PCM_S16LE: #endif/* HAVE_BIGENDIAN */ case AV_CODEC_ID_PCM_U8:
memcpy(dst, samples, n * sample_size); break; #if HAVE_BIGENDIAN case AV_CODEC_ID_PCM_S16BE_PLANAR: #else case AV_CODEC_ID_PCM_S16LE_PLANAR: case AV_CODEC_ID_PCM_S32LE_PLANAR: #endif/* HAVE_BIGENDIAN */
n /= avctx->ch_layout.nb_channels; for (c = 0; c < avctx->ch_layout.nb_channels; c++) { const uint8_t *src = frame->extended_data[c];
bytestream_put_buffer(&dst, src, n * sample_size);
} break; case AV_CODEC_ID_PCM_ALAW: for (; n > 0; n--) {
v = *samples++;
*dst++ = linear_to_alaw[(v + 32768) >> 2];
} break; case AV_CODEC_ID_PCM_MULAW: for (; n > 0; n--) {
v = *samples++;
*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;
}
*got_packet_ptr = 1; return 0;
}
typedefstruct PCMDecode { short table[256]; void (*vector_fmul_scalar)(float *dst, constfloat *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;
switch (avctx->codec_id) { case AV_CODEC_ID_PCM_ALAW: for (i = 0; i < 256; i++)
s->table[i] = alaw2linear(i); break; case AV_CODEC_ID_PCM_MULAW: 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;
if (n && buf_size % n) { if (buf_size < n) {
av_log(avctx, AV_LOG_ERROR, "Invalid PCM packet, data has size %d but at least a size of %d was expected\n",
buf_size, n); return AVERROR_INVALIDDATA;
} else
buf_size -= buf_size % n;
}
n = buf_size / sample_size;
/* get output buffer */
frame->nb_samples = n * samples_per_block / channels; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret;
samples = frame->data[0];
switch (avctx->codec_id) { case AV_CODEC_ID_PCM_U32LE:
DECODE(32, le32, src, samples, n, 0, 0x80000000) break; case AV_CODEC_ID_PCM_U32BE:
DECODE(32, be32, src, samples, n, 0, 0x80000000) break; case AV_CODEC_ID_PCM_S24LE:
DECODE(32, le24, src, samples, n, 8, 0) break; case AV_CODEC_ID_PCM_S24LE_PLANAR:
DECODE_PLANAR(32, le24, src, samples, n, 8, 0); break; case AV_CODEC_ID_PCM_S24BE:
DECODE(32, be24, src, samples, n, 8, 0) break; case AV_CODEC_ID_PCM_U24LE:
DECODE(32, le24, src, samples, n, 8, 0x800000) break; case AV_CODEC_ID_PCM_U24BE:
DECODE(32, be24, src, samples, n, 8, 0x800000) break; case AV_CODEC_ID_PCM_S24DAUD: for (; n > 0; n--) {
uint32_t v = bytestream_get_be24(&src);
v >>= 4; // sync flags are here
AV_WN16A(samples, ff_reverse[(v >> 8) & 0xff] +
(ff_reverse[v & 0xff] << 8));
samples += 2;
} break; case AV_CODEC_ID_PCM_U16LE:
DECODE(16, le16, src, samples, n, 0, 0x8000) break; case AV_CODEC_ID_PCM_U16BE:
DECODE(16, be16, src, samples, n, 0, 0x8000) break; case AV_CODEC_ID_PCM_S8: 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->ch_layout.nb_channels; for (c = 0; c < avctx->ch_layout.nb_channels; c++) { int i;
samples = frame->extended_data[c]; for (i = n; i > 0; i--)
*samples++ = *src++ + 128;
} break; #if HAVE_BIGENDIAN case AV_CODEC_ID_PCM_S64LE: case AV_CODEC_ID_PCM_F64LE:
DECODE(64, le64, src, samples, n, 0, 0) break; case AV_CODEC_ID_PCM_S32LE: case AV_CODEC_ID_PCM_F32LE: case AV_CODEC_ID_PCM_F24LE: case AV_CODEC_ID_PCM_F16LE:
DECODE(32, le32, src, samples, n, 0, 0) break; case AV_CODEC_ID_PCM_S32LE_PLANAR:
DECODE_PLANAR(32, le32, src, samples, n, 0, 0); break; case AV_CODEC_ID_PCM_S16LE:
DECODE(16, le16, src, samples, n, 0, 0) break; case AV_CODEC_ID_PCM_S16LE_PLANAR:
DECODE_PLANAR(16, le16, src, samples, n, 0, 0); break; case AV_CODEC_ID_PCM_F64BE: case AV_CODEC_ID_PCM_F32BE: case AV_CODEC_ID_PCM_S64BE: case AV_CODEC_ID_PCM_S32BE: case AV_CODEC_ID_PCM_S16BE: #else case AV_CODEC_ID_PCM_S64BE: case AV_CODEC_ID_PCM_F64BE:
DECODE(64, be64, src, samples, n, 0, 0) break; case AV_CODEC_ID_PCM_F32BE: case AV_CODEC_ID_PCM_S32BE:
DECODE(32, be32, src, samples, n, 0, 0) break; case AV_CODEC_ID_PCM_S16BE:
DECODE(16, be16, src, samples, n, 0, 0) break; case AV_CODEC_ID_PCM_S16BE_PLANAR:
DECODE_PLANAR(16, be16, src, samples, n, 0, 0); break; case AV_CODEC_ID_PCM_F64LE: case AV_CODEC_ID_PCM_F32LE: case AV_CODEC_ID_PCM_F24LE: case AV_CODEC_ID_PCM_F16LE: case AV_CODEC_ID_PCM_S64LE: case AV_CODEC_ID_PCM_S32LE: case AV_CODEC_ID_PCM_S16LE: #endif/* HAVE_BIGENDIAN */ case AV_CODEC_ID_PCM_U8:
memcpy(samples, src, n * sample_size); break; #if HAVE_BIGENDIAN case AV_CODEC_ID_PCM_S16BE_PLANAR: #else case AV_CODEC_ID_PCM_S16LE_PLANAR: case AV_CODEC_ID_PCM_S32LE_PLANAR: #endif/* HAVE_BIGENDIAN */
n /= avctx->ch_layout.nb_channels; for (c = 0; c < avctx->ch_layout.nb_channels; c++) {
samples = frame->extended_data[c];
bytestream_get_buffer(&src, samples, n * sample_size);
} 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;
} break; case AV_CODEC_ID_PCM_LXF:
{ int i;
n /= channels; for (c = 0; c < channels; c++) {
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++ = ((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++ = ((uint32_t)src[4]<<24) |
(src[3] << 16) |
((src[2] & 0xF0) << 8) |
(src[4] << 4) |
(src[3] >> 4);
src += 5;
}
} break;
} default: return -1;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.