Greetings!
I'm writing a sound library that is capable to load sound files into RAM
for playback (they're completely loaded to RAM and not streamed for
speed reasons) and the format of the sound buffer is specified.
Unfortunately I have problems with audio_resample. I tried to resample
after every frame(s) (in the inner while) or after packet (in the outer
while), which results in cracks and I tried to resample only once
(outside the loops) which resulted in segfaults.
What I'm not sure about is:
* what for are the last 4 parameters of av_audio_resample_init()? - I've
used the default values I found in the code of audio_resample_init()
* when is the user supposed to resample exactly?
* how big has the output buffer for audio_resample() to be?
* according to the documentation audio_resample() wants the number of
samples (nb_samples), but I have to call it with the resulting byte
length I got from avcodec_decode_audio2() (if that acutally really is
the byte count?!) to get the cracking sound, if I divide that value
through (channel * bytes_per_sample) it'll only resample 1/4 of the
sound data it got.
I hope you can help me getting that work! I don't know what to do any
further.
Regards,
neXyon
CODE (resampling in the inner while loop):
Here it should be online for 1 month with a little highlighting:
http://ffmpeg.pastebin.com/m7c10516d
And here is the code in case it is not online anymore:
// open file
AVFormatContext *pFormatCtx;
if(av_open_input_file(&pFormatCtx, m_filename, NULL, 0, NULL)!=0)
return;
if(av_find_stream_info(pFormatCtx)<0)
return;
dump_format(pFormatCtx, 0, m_filename, 0);
// find audio stream and codec
int streamID = -1;
for(int i = 0; i < pFormatCtx->nb_streams; i++)
if((pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) &&
(streamID < 0))
{
streamID=i;
break;
}
if(streamID == -1)
return;
AVCodecContext* aCodecCtx=pFormatCtx->streams[streamID]->codec;
int source_sample_size =
av_get_bits_per_sample_format(aCodecCtx->sample_fmt)/8;
// create a buffer with approximated size
int aBuffer_size = (int)
(
(uint64_t)pFormatCtx->duration *
(
(uint64_t)aCodecCtx->sample_rate *
(uint64_t)aCodecCtx->channels *
(uint64_t)source_sample_size
) / (uint64_t)AV_TIME_BASE +
(uint64_t)AVCODEC_MAX_AUDIO_FRAME_SIZE * 6
);
if(aBuffer_size < 0)
aBuffer_size = 2<<16;
int aBuffer_index = 0;
m_buffer->resize(aBuffer_size);
// get a decoder and open it
AVCodec *aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
if(!aCodec)
return;
avcodec_open(aCodecCtx, aCodec);
// prepare resampling
SND_Server* server = SND_Server::getInstance();
ReSampleContext* rsc = av_audio_resample_init(
server->getChannels(), aCodecCtx->channels,
server->getSampleRate(), aCodecCtx->sample_rate,
SND_TO_FFMPEG(server->getSampleFormat()), aCodecCtx->sample_fmt,
16, 10, 0, 0.8);
// read packages and decode and resample then
AVPacket packet;
int audio_pkt_size;
uint8_t *audio_pkt_data;
int data_size, len;
int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE << 1;
int out_index;
int16_t *in_buffer = (int16_t*)av_malloc(out_size);
int16_t *out_buffer = (int16_t*)av_malloc(out_size);
// for each frame we read
while(av_read_frame(pFormatCtx, &packet)>=0)
{
// is it a frame from our audio stream?
if(packet.stream_index==streamID)
{
// save packet parameters
audio_pkt_data = packet.data;
audio_pkt_size = packet.size;
// as long as there is still data in the package
while(audio_pkt_size > 0)
{
// read samples from the packet
data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE << 1;
len = avcodec_decode_audio2(aCodecCtx,
in_buffer,
&data_size,
audio_pkt_data,
audio_pkt_size);
// read error, next packet!
if(len < 0)
{
audio_pkt_size = 0;
break;
}
// move packet parameters
audio_pkt_data += len;
audio_pkt_size -= len;
// actually read samples?
if(data_size <= 0)
continue;
// resample now!
out_size = audio_resample(rsc,
out_buffer,
in_buffer,
data_size);
// resize buffer if needed
if(aBuffer_size < aBuffer_index + out_size)
{
m_buffer->resize(aBuffer_index + out_size);
aBuffer_size = m_buffer->getSize();
}
// copy data to buffer
memcpy(m_buffer->getBuffer()+aBuffer_index,
out_buffer, out_size);
aBuffer_index += out_size;
}
}
av_free_packet(&packet);
}
if(aBuffer_size > aBuffer_index)
m_buffer->resize(aBuffer_index);
// close and free everything
free(in_buffer);
free(out_buffer);
audio_resample_close(rsc);
av_close_input_file(pFormatCtx);
_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user