[Libav-user] Can't convert raw audio to mp3

daytooner daytooner at gmail.com
Thu Aug 21 19:17:52 CEST 2014


I have a raw audio file (s16, 44100, 2 channels). FWIW, the file was
generated from a FLAC file, and I have tested it in audacity and it is fine.

I am now trying to convert that to an mp3 file. The code I am using follows.
(Note that I have removed a lot of insignificant lines, such as #includes). 

/************************* begin code ********************************
  flac2mp3.cpp
 */
<snip>
# many includes/macros #
<snip>

typedef unsigned char	BYTE;

static AVFormatContext *encfmt_ctx = NULL;
static AVCodecContext *audio_enc_ctx;
static AVStream *audio_encstream = NULL;
static int audio_frame_deccount = 0, audio_frame_enccount = 0;
static SwrContext *swr;

#define	MP3_SAMPLE_FMT	 AV_SAMPLE_FMT_S16P
#define	MP3_BITRATE		256000
#define	MP3_SAMPLE_RATE 	44100

#define	FLAC_SAMPLE_FMT 	AV_SAMPLE_FMT_S16
#define	FLAC_BITRATE		256000
#define	FLAC_SAMPLE_RATE	  44100

#define SAMPLES_TO_CB(stc, cs)
(av_get_bytes_per_sample(stc->codec->sample_fmt) * stc->codec->channels *
cs)
#define SAMPLES_FROM_CB(stc, cb)
cb/(av_get_bytes_per_sample(stc->codec->sample_fmt) * stc->codec->channels)

#define	BYTES_TO_READ   	4594

void flush_audio()
{
	int ret;
	int	got_frame;
	AVPacket	epkt = {0};

	av_init_packet(&epkt);
	do
	{
	ret = avcodec_encode_audio2(audio_enc_ctx, &epkt, NULL, &got_frame);
	av_assert0(ret >= 0);
	}while(got_frame);
}

/*
 * encode a buffer of cbdec bytes of raw audio
*/
bool encode_buffer(BYTE* buff, int cbdec)
{
	int ret;
	int	got_frame;
	int	line_size;
	BYTE*	ob[2];
	const BYTE*	ib[2];
	AVPacket	epkt = {0};
	AVFrame *eframe = avcodec_alloc_frame();

	av_init_packet(&epkt);
	/*
	 * convert audio
	 */
	long int c_insamples = cbdec/(4);
//	long int delay = swr_get_delay(swr,(long int) 44100);
	long int delay = 0;
	int c_outsamples = av_rescale_rnd(delay + c_insamples,
			(long int) MP3_SAMPLE_RATE,
			(long int) FLAC_SAMPLE_RATE, AV_ROUND_UP);
	ret = av_samples_alloc(ob, &line_size, 2,
					c_outsamples,MP3_SAMPLE_FMT, 0);
	av_assert0(ret >= 0);
	ib[0] = buff;
	ret = swr_convert(swr, ob, c_outsamples, ib, c_insamples);
	av_assert0(ret >= 0);

	/*
	 * encode
	 */
	eframe->nb_samples = cbdec/(4);
	eframe->pts = (audio_frame_deccount * ( av_rescale_q(1,
audio_encstream->codec->time_base, audio_encstream->time_base)));
	avcodec_fill_audio_frame(eframe, 2, MP3_SAMPLE_FMT, ob[0], cbdec, 1);

	epkt.stream_index = audio_encstream->index;
	eframe->nb_samples = audio_enc_ctx->frame_size;

	ret = avcodec_encode_audio2(audio_enc_ctx, &epkt, eframe, &got_frame);
	av_assert0(ret >= 0);
	audio_frame_deccount +=(cbdec/4);
	printf("cbdec=%d, decoded=%d pts=%ld\n", cbdec, audio_frame_deccount,
eframe->pts);
	if (!got_frame)
	{
		return false;
	}
	epkt.stream_index = audio_encstream->index;
	audio_frame_enccount ++ ;
	/* Write the compressed frame to the media file. */
	ret = av_interleaved_write_frame(encfmt_ctx, &epkt);

	av_free(ob[0]);
	avcodec_free_frame(&eframe);
	return true;

}


int open_encodec_context(AVFormatContext *fmt_ctx, enum AVMediaType type)
{
	int ret;
	AVStream *st;
	AVCodec *enc = NULL;
	enc = avcodec_find_encoder(fmt_ctx->oformat->audio_codec);
	av_assert0(enc != NULL);
	st = avformat_new_stream(fmt_ctx, enc);
	/* find encoder for the stream */
	st->codec->sample_fmt = MP3_SAMPLE_FMT;
	st->codec->bit_rate = MP3_BITRATE;
	st->codec->sample_rate = MP3_SAMPLE_RATE;
	st->codec->channels = 2;
	st->codec->channel_layout = 3;
	ret = avcodec_open2(st->codec, enc, NULL);
	av_assert0(ret >= 0);


	return 1;
}


int main(int argc, char **argv)
{

	const char *fn_out = argv[1];
	int ret;

	av_register_all();
	ret = avformat_alloc_output_context2(&encfmt_ctx, NULL, NULL, fn_out);
	av_assert0(ret >= 0);
	if (open_encodec_context(encfmt_ctx, AVMEDIA_TYPE_AUDIO) >= 0)
	{

		audio_encstream = encfmt_ctx->streams[0];
		audio_enc_ctx = audio_encstream->codec;
		av_dump_format(encfmt_ctx, 0, fn_out, 1);
	}

	swr = swr_alloc();
	av_assert0(swr);

	/* set options */
	av_opt_set_int(swr, "in_channel_layout", 3, 0);
	av_opt_set_int(swr, "in_channel_count", 2, 0);
	av_opt_set_int(swr, "in_sample_rate", FLAC_SAMPLE_RATE,0);
	av_opt_set_sample_fmt(swr, "in_sample_fmt", FLAC_SAMPLE_FMT, 0);
	av_opt_set_int(swr, "out_channel_layout",3, 0);
	av_opt_set_int(swr, "out_sample_rate", MP3_SAMPLE_RATE, 0);
	av_opt_set_sample_fmt(swr, "out_sample_fmt",MP3_SAMPLE_FMT, 0);
	ret = swr_init(swr);
	av_assert0(ret >= 0);

	if (!(encfmt_ctx->oformat->flags & AVFMT_NOFILE))
	{
		ret = avio_open(&encfmt_ctx->pb, fn_out, AVIO_FLAG_WRITE);
                av_assert0(ret >= 0);
	}
	ret = avformat_write_header(encfmt_ctx, NULL);
	av_assert0(ret >= 0);

	int cbread = 0;
	int	fd = open("/nas/temp/flac.raw", O_RDONLY);
	assert(fd > 0);
	int cb2read = BYTES_TO_READ;
	BYTE	b[cb2read];
	int c_reads = 0;
	while ((cbread = read(fd, b, cb2read)) > 0)
	{
		c_reads++;
		encode_buffer(b, cbread);
	}
	avcodec_flush_buffers(audio_enc_ctx);
	flush_audio();
	close(fd);
	ret = av_interleaved_write_frame(encfmt_ctx, NULL);
	av_assert0(ret >= 0);

	av_write_trailer(encfmt_ctx);
	avio_close(encfmt_ctx->pb);

	avcodec_close(audio_enc_ctx);
	avformat_free_context(encfmt_ctx);
	exit(1);
}
/**************** end code *************************/

I have discovered that if I change the number of bytes read in and encoded
(BYTES_TO_READ), that the output changes. I experimented with different
values, and the value 4594 seems to get the closest to the original audio -
although it it about 0.5 seconds longer and the audio is choppy. Also, with
some values of BYTES_TO_READ, the avcodec_encode_audio2  call fails, with an
error of "not enough bytes".

I would like to transcode directly from the flac file to mp3, as the ffmpeg
command line does, as well as take raw audio and encode it to mp3 and other
formats.

So, the basic question is: what is wrong with the above code? I have pieced
this together from the various libav samples on the ffmpeg website.

Also, in the future, I will need to do the same thing with video - encode
raw video in various pixel formats. So, any help here is greatly
appreciated.

TIA

ken

PS: sorry for the long message, but I did feel the code was important.




--
View this message in context: http://libav-users.943685.n4.nabble.com/Can-t-convert-raw-audio-to-mp3-tp4660311.html
Sent from the libav-users mailing list archive at Nabble.com.


More information about the Libav-user mailing list