[Libav-user] Audio file is not getting created.
Prakash Rokade
prakash.rokade420 at gmail.com
Thu Feb 9 10:39:31 EET 2017
I am trying to record audio from speaker.
I am using below code to create audio file.
The audio file is created but there is no audio data in file.
Or some time only 2-3 sec of audio data is recorded.
I have gone through the ffmpeg examples.
can some one help me by seeing the below code.
Thanks.
ref struct WriterData
{
public:
Ffmpeg::AVFormatContext* FormatContext;
Ffmpeg::AVStream* AudioStream;
Ffmpeg::AVFrame* AudioFrame;
Ffmpeg::AVCodec *Audio_Codec;
int AudioBitRate;
int SampleRate;
int Channels;
int AudioReceived;
int AudioWritten;
Ffmpeg::int64_t next_pts;
int samples_count;
Ffmpeg::AVFrame *tmp_frame;
float t, tincr, tincr2;
struct Ffmpeg::SwsContext *sws_ctx;
struct Ffmpeg::SwrContext *swr_ctx;
double PreviousAudioDts;
AudioWriterData()
{
FormatContext = NULL;
AudioStream = NULL;
Audio_Codec = NULL;
AudioFrame = NULL;
AudioReceived = 0;
AudioWritten = 0;
}
};
void Encoder::Open(String^ fileName, AudioCodec audioCodec, int
audioBitrate, int sampleRate, int channels)
{
CheckIfDisposed();
Close();
data = gcnew WriterData();
bool success = false;
if (((int)audioCodec < -1) || ((int)audioCodec >= AUDIO_CODECS_COUNT))
throw gcnew ArgumentException("Invalid audio codec is specified.");
m_acodec = audioCodec;
m_audioBitrate = audioBitrate;
m_sampleRate = sampleRate;
m_channels = channels;
data->AudioBitRate = audioBitrate;
data->SampleRate = sampleRate;
data->Channels = channels;
char* nativeFileName =
(char*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(fileName).ToPointer();
try
{
Ffmpeg::AVOutputFormat* outputFormat = Ffmpeg::av_guess_format(NULL,
nativeFileName, NULL);
if (!outputFormat)
{
outputFormat = Ffmpeg::av_guess_format("mp3", NULL, NULL);
if (!outputFormat)
throw gcnew Exception("Cannot find suitable output format.");
}
data->FormatContext = Ffmpeg::avformat_alloc_context();
if (!data->FormatContext)
throw gcnew Exception("Cannot allocate format context.");
data->FormatContext->oformat = outputFormat;
strcpy_s(data->FormatContext->filename, nativeFileName);
Ffmpeg::AVCodecID codecId = (audioCodec == AudioCodec::Default) ?
outputFormat->audio_codec : (Ffmpeg::AVCodecID)
audio_codecs[(int)audioCodec];
data->FormatContext->oformat->audio_codec = codecId;
add_audio_stream(data, codecId);
open_audio(data);
Ffmpeg::av_dump_format(data->FormatContext, 0, nativeFileName, 1);
if (!(outputFormat->flags & AVFMT_NOFILE))
{
if (Ffmpeg::avio_open(&data->FormatContext->pb, nativeFileName,
AVIO_FLAG_WRITE) < 0)
throw gcnew System::IO::IOException("Cannot open the video file.");
}
Ffmpeg::avformat_write_header(data->FormatContext, NULL);
success = true;
}
finally
{
nativeFileName = NULL;
delete[] nativeFileName;
if (!success)
Close();
}
}
void add_audio_stream(WriterData^ data, enum Ffmpeg::AVCodecID codecId)
{
data->AudioStream = Ffmpeg::avformat_new_stream(data->FormatContext,
data->FormatContext->audio_codec);
if (!data->AudioStream)
throw gcnew Exception("Could not alloc audio stream");
Ffmpeg::AVCodecContext *codecContext = data->AudioStream->codec;
codecContext->codec_id = codecId;
codecContext->codec_type = Ffmpeg::AVMEDIA_TYPE_AUDIO;
codecContext->sample_fmt = Ffmpeg::AV_SAMPLE_FMT_S16;
codecContext->channels = data->Channels;
codecContext->delay = 0;
codecContext->bit_rate = data->AudioBitRate;
if (codecContext->bit_rate == 0)
codecContext->bit_rate = data->SampleRate * data->Channels * 16;
codecContext->bit_rate = codecContext->bit_rate;
codecContext->bit_rate_tolerance = codecContext->bit_rate;
codecContext->rc_min_rate = 0;
codecContext->rc_max_rate = 0;
codecContext->frame_size = 0;
codecContext->channel_layout = (codecContext->channels == 2 ?
AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO);
codecContext->sample_rate = data->SampleRate;
codecContext->time_base.den = data->SampleRate;
codecContext->time_base.num = 1;
//data->AudioStream->time_base.den = codecContext->time_base.den;
//data->AudioStream->time_base.num = codecContext->time_base.num;
if (data->FormatContext->oformat->flags & AVFMT_GLOBALHEADER)
codecContext->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
void open_audio(WriterData^ data)
{
Ffmpeg::AVCodecContext* codecContext = data->AudioStream->codec;
Ffmpeg::AVCodec* codec = avcodec_find_encoder(codecContext->codec_id);
if (!codec)
throw gcnew Exception("Cannot find audio codec.");
codecContext->codec_id = codec->id;
codecContext->codec_type = Ffmpeg::AVMEDIA_TYPE_AUDIO;
codecContext->sample_fmt = codec->sample_fmts[0];
codecContext->sample_rate = data->SampleRate;
codecContext->channel_layout = AV_CH_LAYOUT_STEREO;
codecContext->channels =
Ffmpeg::av_get_channel_layout_nb_channels(codecContext->channel_layout);
codecContext->bit_rate = data->AudioBitRate;
int ret = Ffmpeg::avcodec_open2(codecContext, codec, NULL);
if (ret < 0)
throw gcnew Exception("Cannot open audio codec.");
}
void Encoder::WriteAudioChunk(IntPtr chunk, int lenght, TimeSpan timestamp)
{
CheckIfDisposed();
if (data == nullptr)
throw gcnew System::IO::IOException("A video file was not opened yet.");
int bufferSize = lenght;
data->AudioFrame = Ffmpeg::av_frame_alloc();
Ffmpeg::av_frame_unref(data->AudioFrame);
data->AudioFrame->pts = AV_NOPTS_VALUE;
data->AudioFrame->format = data->AudioStream->codec->sample_fmt;
int bytePerSample =
Ffmpeg::av_get_bytes_per_sample(data->AudioStream->codec->sample_fmt);
int dataSize = data->Channels * bytePerSample;
data->AudioStream->codec->frame_size = data->Channels *
data->SampleRate * bytePerSample;
data->AudioFrame->nb_samples = data->AudioStream->codec->frame_size;
Ffmpeg::uint8_t *buf =
reinterpret_cast<Ffmpeg::uint8_t*>(static_cast<void*>(chunk));
int ret = Ffmpeg::avcodec_fill_audio_frame(data->AudioFrame,
data->Channels, data->AudioStream->codec->sample_fmt, buf, bufferSize,
1);
if (!ret)
throw gcnew System::IO::IOException("A video file was not opened yet.");
data->AudioReceived++;
write_audio_chunk(data, buf, ret,timestamp.TotalMilliseconds);
}
void write_audio_chunk(WriterData^ data, Ffmpeg::uint8_t *ut, int
size,double timeStamp)
{
Ffmpeg::AVCodecContext* codecContext = data->AudioStream->codec;
int out_size, ret = 0;
Ffmpeg::AVPacket packet;
int64_t dts = timeStamp;
dts = dts * data->FrameRate;
if (data->PreviousAudioDts < 0)
data->PreviousAudioDts = dts;
int got_packet;
Ffmpeg::av_init_packet(&packet);
packet.data = ut;
packet.size = size;
out_size = Ffmpeg::avcodec_send_frame(codecContext, data->AudioFrame);
got_packet = Ffmpeg::avcodec_receive_packet(codecContext, &packet);
if (got_packet)
{
if (codecContext->coded_frame->pts != AV_NOPTS_VALUE)
{
packet.pts = Ffmpeg::av_rescale_q(packet.pts,
codecContext->time_base, data->AudioStream->time_base);
packet.dts = Ffmpeg::av_rescale_q(packet.dts,
codecContext->time_base, data->AudioStream->time_base);
packet.duration = Ffmpeg::av_rescale_q(packet.duration,
codecContext->time_base, data->AudioStream->time_base);
}
packet.stream_index = data->AudioStream->index;
ret = Ffmpeg::av_interleaved_write_frame(data->FormatContext, &packet);
//ret = Ffmpeg::av_write_frame(data->FormatContext, &packet);
data->AudioWritten++;
}
av_packet_unref(&packet);
got_packet = 0;
if (ret != 0)
throw gcnew Exception("Error while writing audio frame.");
}
More information about the Libav-user
mailing list