[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