[Libav-user] IntPtr to Packet data is not woking
Prakash Rokade
prakash.rokade420 at gmail.com
Tue Feb 21 10:32:26 EET 2017
Thanks for reply...
The code is only sample, and method writeaudiochunk is get called from
outside.
I am using directshow graph as audio source.
if you want full code I can give it to you.
Now the sample is working. But I have recorded audio for 2 min but output
file has only 3 sec duration and audio is also so fast...
Can you make some suggestions...
On 20 Feb 2017 22:42, "Gonzalo Garramuno" <ggarra13 at gmail.com> wrote:
> 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::Intero
> pServices::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*>(sta
> tic_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*>(sta
> tic_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
>
>
>
> _______________________________________________
> 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/20170221/b8610162/attachment.html>
More information about the Libav-user
mailing list