📄 pcm.c
字号:
/*
* 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
*/
/**
* @file pcm.c
* PCM codecs
*/
#include "avcodec.h"
/* from g711.c by SUN microsystems (unrestricted use) */
#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
#define QUANT_MASK (0xf) /* Quantization field mask. */
#define NSEGS (8) /* Number of A-law segments. */
#define SEG_SHIFT (4) /* Left shift for segment number. */
#define SEG_MASK (0x70) /* Segment field mask. */
#define BIAS (0x84) /* Bias for linear code. */
/*
* alaw2linear() - Convert an A-law value to 16-bit linear PCM
*
*/
static int alaw2linear(unsigned char a_val)
{
int t;
int seg;
a_val ^= 0x55;
t = a_val & QUANT_MASK;
seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
if(seg) t= (t + t + 1 + 32) << (seg + 2);
else t= (t + t + 1 ) << 3;
return ((a_val & SIGN_BIT) ? t : -t);
}
static int ulaw2linear(unsigned char u_val)
{
int t;
/* Complement to obtain normal u-law value. */
u_val = ~u_val;
/*
* Extract and bias the quantization bits. Then
* shift up by the segment number and subtract out the bias.
*/
t = ((u_val & QUANT_MASK) << 3) + BIAS;
t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
}
typedef struct PCMDecode {
short table[256];
} PCMDecode;
static int pcm_decode_init(AVCodecContext * avctx)
{
PCMDecode *s = avctx->priv_data;
int i;
switch(avctx->codec->id) {
case CODEC_ID_PCM_ALAW:
for(i=0;i<256;i++)
s->table[i] = alaw2linear(i);
break;
case CODEC_ID_PCM_MULAW:
for(i=0;i<256;i++)
s->table[i] = ulaw2linear(i);
break;
default:
break;
}
return 0;
}
static int pcm_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
uint8_t *buf, int buf_size)
{
PCMDecode *s = avctx->priv_data;
int n;
short *samples;
uint8_t *src;
samples = data;
src = buf;
n= av_get_bits_per_sample(avctx->codec_id)/8;
if(n && buf_size % n){
av_log(avctx, AV_LOG_ERROR, "invalid PCM packet\n");
return -1;
}
if(buf_size > AVCODEC_MAX_AUDIO_FRAME_SIZE/2)
buf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE/2;
switch(avctx->codec->id) {
case CODEC_ID_PCM_ALAW:
case CODEC_ID_PCM_MULAW:
n = buf_size;
for(;n>0;n--) {
*samples++ = s->table[*src++];
}
break;
default:
return -1;
}
*data_size = (uint8_t *)samples - (uint8_t *)data;
return src - buf;
}
#define PCM_CODEC(id, name) \
AVCodec name ## _decoder = { \
#name, \
CODEC_TYPE_AUDIO, \
id, \
sizeof(PCMDecode), \
pcm_decode_init, \
NULL, \
NULL, \
pcm_decode_frame, \
}
PCM_CODEC(CODEC_ID_PCM_ALAW, pcm_alaw);
PCM_CODEC(CODEC_ID_PCM_MULAW, pcm_mulaw);
#undef PCM_CODEC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -