[Libav-user] Convert AMR NB to PCM problem
Tăng Phương Quý
quy.tangphuong at gmail.com
Wed Mar 26 08:04:08 CET 2014
Dear sir,
I need to convert in memory amr file to pcm, but after it has been coverted,
the data was far different from the original and double the audio sample.
Here is my code:
#define AUDIO_INBUF_SIZE 20480#define AUDIO_REFILL_THRESH 4096#define
AMR_NB_HEADER_SIZE 6#define WAV_RIFF_HEADER_SIZE 44#define
OGG_POLYMNOMIAL 0x04C11DB7#define OGG_PAGE_HEADER 27
class Buffer {public:
void* buffer;
int size;
public:
Buffer() {
buffer = NULL;
size = 0;
}
void resize(int newSize) {
if (newSize > 0 && newSize != size) {
size = newSize;
buffer = realloc(buffer, size);
}
}
void extend(int extendSize) {
if (extendSize > 0) {
size += extendSize;
buffer = realloc(buffer, size);
}
}
void free() {
size = 0;
if (buffer != NULL) {
::free(buffer);
buffer = NULL;
}
}};void AudioProcessor::fillPCMRIFFHeader(void* buffer, int16_t
channels, int16_t bps, int pcmSizeInBytes, int samplingRate) {
//ChunkID - RIFF
*((int8_t*) buffer) = 0x52;
*((int8_t*) buffer + 1) = 0x49;
*((int8_t*) buffer + 2) = 0x46;
*((int8_t*) buffer + 3) = 0x46;
//ChunkSize
*((int32_t *) ((int8_t*) buffer + 4)) = 36 + pcmSizeInBytes;
//Format - WAVE
*((int8_t*) buffer + 8) = 0x57;
*((int8_t*) buffer + 9) = 0x41;
*((int8_t*) buffer + 10) = 0x56;
*((int8_t*) buffer + 11) = 0x45;
//Subchunk1ID - "fmt "
*((int8_t*) buffer + 12) = 0x66;
*((int8_t*) buffer + 13) = 0x6d;
*((int8_t*) buffer + 14) = 0x74;
*((int8_t*) buffer + 15) = 0x20;
//Subchunk1Size
*((int8_t*) buffer + 16) = 0x10;
*((int8_t*) buffer + 17) = 0x00;
*((int8_t*) buffer + 18) = 0x00;
*((int8_t*) buffer + 19) = 0x00;
//AudioFormat
*((int8_t*) buffer + 20) = 0x01;
*((int8_t*) buffer + 21) = 0x00;
//NumChannels
if (channels == 2) {
*((int8_t*) buffer + 22) = 0x2;
} else {
*((int8_t*) buffer + 22) = 0x1;
}
*((int8_t*) buffer + 23) = 0x00;
//SampleRate
*((int32_t *)((int8_t*) buffer + 24)) = samplingRate;
//ByteRate
*((int32_t *)((int8_t*) buffer + 28)) = samplingRate * 2;
//BlockAlign
*((int16_t *)((int8_t*) buffer + 32)) = 2;
//BitsPerSample
*((int16_t *)((int8_t*) buffer + 34)) = 16;
//Subchunk2ID - data
*((int8_t*) buffer + 36) = 0x64;
*((int8_t*) buffer + 37) = 0x61;
*((int8_t*) buffer + 38) = 0x74;
*((int8_t*) buffer + 39) = 0x61;
//Subchunk2Size
*((int32_t *)((int8_t*) buffer + 40)) = pcmSizeInBytes;}void
AudioProcessor::amrnbToPCM(const Buffer* in, Buffer* out) {
AVCodec *codec;
AVCodecContext *c = NULL;
int len;
uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
AVPacket avpkt;
AVFrame *decoded_frame = NULL;
av_init_packet(&avpkt);
codec = avcodec_find_decoder(AV_CODEC_ID_AMR_NB);
if (!codec) {
return;
}
c = avcodec_alloc_context3(codec);
if (!c) {
return;
}
if (avcodec_open2(c, codec, NULL) < 0) {
return;
}
avpkt.data = inbuf;
int inOffset = AUDIO_INBUF_SIZE;
if (inOffset > in->size - AMR_NB_HEADER_SIZE) {
inOffset = in->size - AMR_NB_HEADER_SIZE;
}
printf("inOffset: %d\n", inOffset);
memcpy(inbuf, (int8_t*) in->buffer + AMR_NB_HEADER_SIZE, inOffset);
avpkt.size = inOffset;
avpkt.dts = avpkt.pts = AV_NOPTS_VALUE;
inOffset += AMR_NB_HEADER_SIZE;
printf("inOffset: %d\n", inOffset);
printf("outSize: %d\n", out->size);
out->resize(60000);
printf("outSize: %d\n", out->size);
int outLen = WAV_RIFF_HEADER_SIZE;
decoded_frame = av_frame_alloc();
int sampleRate = 8000;
while (avpkt.size > 0) {
int got_frame = 0;
if (!decoded_frame) {
decoded_frame = av_frame_alloc();
}
len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt);
if (len < 0) {
printf("break\n");
break;
}
printf("gotframe: %d - %d\n", got_frame, len);
if (got_frame) {
int data_size = av_samples_get_buffer_size(NULL, c->channels,
decoded_frame->nb_samples,
c->sample_fmt, 1);
sampleRate = decoded_frame->sample_rate;
while (outLen + data_size > out->size) {
out->extend(6000);
}
memcpy((int8_t*) out->buffer + outLen,
decoded_frame->data[0], data_size);
outLen += data_size;
av_frame_free(&decoded_frame);
decoded_frame = NULL;
}
avpkt.size -= len;
avpkt.data += len;
avpkt.dts = avpkt.pts = AV_NOPTS_VALUE;
if (avpkt.size < AUDIO_REFILL_THRESH && inOffset < in->size) {
if (avpkt.size > 0) {
memmove(inbuf, avpkt.data, avpkt.size);
}
avpkt.data = inbuf;
if (inOffset + len > in->size) {
len = in->size - inOffset;
}
if (len > 0) {
memcpy(avpkt.data + avpkt.size, (int8_t*)in->buffer
+ inOffset, len);
inOffset += len;
avpkt.size += len;
}
}
}
int pcmSizeInBytes = outLen - WAV_RIFF_HEADER_SIZE;
fillPCMRIFFHeader(out->buffer, 1, 16, pcmSizeInBytes, sampleRate);
out->size = outLen;
avcodec_close(c);
av_free(c);
if (decoded_frame) {
av_frame_free(&decoded_frame);
}
}
Please help me pointing out what I am wrong.
Input file: http://www.mediafire.com/download/0kw3n35z363x9ka/_01.amr
Thank you very much,
QuyTang
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20140326/068951ca/attachment.html>
More information about the Libav-user
mailing list