[Libav-user] IntPtr to Packet data is not woking
Gonzalo Garramuno
ggarra13 at gmail.com
Mon Feb 20 19:12:40 EET 2017
I am unable to compile your code, but at first glance you are missing the
main loop. The one that would call writeaudiochunk.
El feb. 20, 2017 12:41 PM, "Prakash Rokade" <prakash.rokade420 at gmail.com>
escribió:
Hiii Gonzalo Garramuño,
I have modified the code but there is issue that i am not able to figure
out.
No error while encoding, resampling , and writting the audio data. But
output file only have the 1 sec audio. can you check the code and suggest
some changes.
ref struct AudioWriterData
{
public:
Ffmpeg::AVFormatContext* FormatContext;
Ffmpeg::AVStream* AudioStream;
Ffmpeg::AVFrame* AudioFrame;
Ffmpeg::AVCodec *Audio_Codec;
int AudioBitRate;
int SampleRate;
int Channels;
int AudioReceived;
int AudioWritten;
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;
double EncodedAudioFrame;
AudioWriterData()
{
FormatContext = NULL;
AudioStream = NULL;
Audio_Codec = NULL;
AudioFrame = NULL;
AudioReceived = 0;
AudioWritten = 0;
EncodedAudioFrame = 0;
}
};
//Open the audio file with specified settings
void AudioWriter::Open(String^ fileName, AudioCodec audioCodec, int
audioBitrate, int sampleRate, int channels)
{
CheckIfDisposed();
Close();
data = gcnew AudioWriterData();
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 avcodecid = (audioCodec ==
AudioCodec::Default) ? outputFormat->audio_codec : (Ffmpeg::AVCodecID)
audio_codecs[(int)audioCodec];
data->FormatContext->oformat->audio_codec = avcodecid;
add_stream(data, data->FormatContext, data->Audio_Codec,
avcodecid);
open_audio(data->FormatContext, data->Audio_Codec, 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
audio file.");
}
Ffmpeg::avformat_write_header(data->FormatContext, NULL);
success = true;
}
finally
{
nativeFileName = NULL;
delete[] nativeFileName;
if (!success)
Close();
}
}
static void add_stream(AudioWriterData^ ost, Ffmpeg::AVFormatContext
*oc, Ffmpeg::AVCodec *codec, enum Ffmpeg::AVCodecID codec_id)
{
Ffmpeg::AVCodecContext *c;
int i;
codec = Ffmpeg::avcodec_find_encoder(codec_id);
if (!(codec))
throw gcnew Exception("Invalid audio codec is specified.");
ost->AudioStream = Ffmpeg::avformat_new_stream(oc, codec);
if (!ost->AudioStream)
throw gcnew Exception("Unable to add audio stream.");
ost->AudioStream->id = oc->nb_streams - 1;
c = ost->AudioStream->codec;
c->sample_fmt = (codec)->sample_fmts ? (codec)->sample_fmts[0] :
Ffmpeg::AV_SAMPLE_FMT_FLTP;
c->bit_rate = ost->AudioBitRate;
c->sample_rate = 44100;
if ((codec)->supported_samplerates)
{
c->sample_rate = (codec)->supported_samplerates[0];
for (i = 0; (codec)->supported_samplerates[i]; i++)
{
if ((codec)->supported_samplerates[i] == 44100)
c->sample_rate = 44100;
}
}
c->channels = Ffmpeg::av_get_channel_layout_
nb_channels(c->channel_layout);
c->channel_layout = AV_CH_LAYOUT_STEREO;
if ((codec)->channel_layouts)
{
c->channel_layout = (codec)->channel_layouts[0];
for (i = 0; (codec)->channel_layouts[i]; i++)
{
if ((codec)->channel_layouts[i] == AV_CH_LAYOUT_STEREO)
c->channel_layout = AV_CH_LAYOUT_STEREO;
}
}
c->channels = Ffmpeg::av_get_channel_layout_
nb_channels(c->channel_layout);
ost->AudioStream->time_base.num = 1;
ost->AudioStream->time_base.den = c->sample_rate;
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
static Ffmpeg::AVFrame *alloc_audio_frame(enum Ffmpeg::AVSampleFormat
sample_fmt,uint64_t channel_layout,int sample_rate, int nb_samples)
{
Ffmpeg::AVFrame *frame = Ffmpeg::av_frame_alloc();
int ret;
if (!frame)
throw gcnew Exception("Unable to allocate frame.");
frame->format = sample_fmt;
frame->channel_layout = channel_layout;
frame->sample_rate = sample_rate;
frame->nb_samples = nb_samples;
if (nb_samples)
{
ret = av_frame_get_buffer(frame, 0);
if (ret < 0)
throw gcnew Exception("Unable to buffer frame.");
}
return frame;
}
static void open_audio(Ffmpeg::AVFormatContext *oc, Ffmpeg::AVCodec
*codec, AudioWriterData^ ost)
{
Ffmpeg::AVCodecContext *c;
int nb_samples;
int ret;
c = ost->AudioStream->codec;
ret = avcodec_open2(c, codec, NULL);
if (ret < 0)
throw gcnew Exception("Cannot open audio codec.");
ost->t = 0;
ost->tincr = 2 * M_PI * 110.0 / c->sample_rate;
ost->tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;
if (c->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
nb_samples = 10000;
else
nb_samples = c->frame_size;
ost->AudioFrame = alloc_audio_frame(c->sample_fmt,
c->channel_layout, c->sample_rate, nb_samples);
ost->tmp_frame = alloc_audio_frame(Ffmpeg::AV_SAMPLE_FMT_S16,
c->channel_layout, c->sample_rate, nb_samples);
ost->swr_ctx = Ffmpeg::swr_alloc();
if (!ost->swr_ctx)
throw gcnew Exception("Could not allocate resampler context.");
Ffmpeg::av_opt_set_int(ost->swr_ctx, "in_channel_count",
c->channels, 0);
Ffmpeg::av_opt_set_int(ost->swr_ctx, "in_sample_rate",
c->sample_rate, 0);
Ffmpeg::av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt",
Ffmpeg::AV_SAMPLE_FMT_S16, 0);
Ffmpeg::av_opt_set_int(ost->swr_ctx, "out_channel_count",
c->channels, 0);
Ffmpeg::av_opt_set_int(ost->swr_ctx, "out_sample_rate",
c->sample_rate, 0);
Ffmpeg::av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt",
c->sample_fmt, 0);
if ((ret = Ffmpeg::swr_init(ost->swr_ctx)) < 0)
throw gcnew Exception("Failed to initialize the resampling
context.");
}
void AudioWriter::WriteAudioChunk(IntPtr chunk, int lenght)
{
uint8_t *audioData = reinterpret_cast<uint8_t*>(
static_cast<void*>(chunk));
int buffer_size = Ffmpeg::av_samples_get_buffer_size(NULL,
data->tmp_frame->channels, data->tmp_frame->nb_samples,
data->AudioStream->codec->sample_fmt, 0);
uint8_t *buf = reinterpret_cast<uint8_t*>(
static_cast<void*>(chunk));
int ret = Ffmpeg::avcodec_fill_audio_frame(data->tmp_frame,
data->Channels, data->AudioStream->codec->sample_fmt, buf, buffer_size, 1);
if (!ret)
throw gcnew System::IO::IOException("A video file was not
opened yet.");
write_audio_frame(data->FormatContext, data, audioData);
}
static int write_audio_frame(Ffmpeg::AVFormatContext *oc,
AudioWriterData^ ost, uint8_t *audioData)
{
Ffmpeg::AVCodecContext *c;
Ffmpeg::AVPacket pkt = { 0 };
int ret;
int got_packet;
int dst_nb_samples;
Ffmpeg::av_init_packet(&pkt);
c = ost->AudioStream->codec;
Ffmpeg::AVFrame *frame = ost->tmp_frame;
if (frame)
{
dst_nb_samples = Ffmpeg::av_rescale_rnd(swr_get_delay(ost->swr_ctx,
c->sample_rate) + frame->nb_samples,
c->sample_rate, c->sample_rate, Ffmpeg::AV_ROUND_UP);
if (dst_nb_samples != frame->nb_samples)
throw gcnew Exception("dst_nb_samples !=
frame->nb_samples");
ret = Ffmpeg::av_frame_make_writable(ost->AudioFrame);
if (ret < 0)
throw gcnew Exception("Unable to make writable.");
ret = swr_convert(ost->swr_ctx, ost->AudioFrame->data,
dst_nb_samples, (const uint8_t **)frame->data, frame->nb_samples);
if (ret < 0)
throw gcnew Exception("Unable to convert to destination
format.");
frame = ost->AudioFrame;
Ffmpeg::AVRational timebase = { 1, c->sample_rate };
frame->pts = Ffmpeg::av_rescale_q(ost->samples_count, timebase,
c->time_base);
ost->samples_count += dst_nb_samples;
}
ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
if (ret < 0)
throw gcnew Exception("Error encoding audio frame.");
if (got_packet)
{
Console::WriteLine("Audio packet encode successfully.");
ret = write_frame(oc, &c->time_base, ost->AudioStream, &pkt);
if (ret < 0)
Console::WriteLine("Audio is not written.");
}
else
Console::WriteLine("Audio packet encode failed.");
return (ost->AudioFrame || got_packet) ? 0 : 1;
}
static int write_frame(Ffmpeg::AVFormatContext *fmt_ctx, const
Ffmpeg::AVRational *time_base, Ffmpeg::AVStream *st, Ffmpeg::AVPacket *pkt)
{
Ffmpeg::av_packet_rescale_ts(pkt, *time_base, st->time_base);
pkt->stream_index = st->index;
return Ffmpeg::av_interleaved_write_frame(fmt_ctx, pkt);
}
On 16 February 2017 at 03:13, Gonzalo Garramuño <ggarra13 at gmail.com> wrote:
>
>
> El 15/02/17 a las 03:58, Prakash Rokade escribió:
>
> Thanks Gonzalo,
>
> According to your suggestion i have written the below code can you check
> ones, because audio is written but in output file no audio is present.
>
> You are opening the stream with AV_SAMPLE_FMT_S16 and then using
> sample_fmt[0]. That's inconsistent to say the least.
> You are not using swresample to take one audio format to another.
> You have a swscale ptr which has nothing to do with audio.
> You are using the new API but are not handling the AVERROR(EAGAIN) cases.
> For this trial, use the old api which is more reliable for muxing.
> Try to get the sample in doc/examples working and slowly modify it to fit
> your need.
>
> --
> Gonzalo Garramuño
>
>
> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/libav-user
>
>
_______________________________________________
Libav-user mailing list
Libav-user at ffmpeg.org
http://ffmpeg.org/mailman/listinfo/libav-user
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20170220/df89a974/attachment.html>
More information about the Libav-user
mailing list