[Libav-user] Incorrect compressed audio

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[Libav-user] Incorrect compressed audio

Jonathan Noble
Hi,
I don't know why I am not getting a reply to my previous e-mails, so I am trying again. Please let me know if they were there.

I have a pipeline of reader->decoder->encoder->writer where the codec parameters are the same on encoder and decoder.
The resultant file has audio that is distorted and considerably shorter than the file that was being read from. There are no messages returned from ffmpeg to indicate anything going wrong.

I've spent the last week looking into this and i've not got any further than at the start. Instead of posting my original code I thought i'd make a small representation of my code use ffmpeg calls only.

What is it that I am missing? Are my e-mails getting through?
Thanks in advance.
Jon Noble

### The code ###

#include <assert.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <stdio.h>

const char* source = "/home/jon/Projects/Code/mediahandling/RegressionTests/ReferenceMedia/Audio/ogg/monotone.ogg";
const char* destination = "/tmp/vorbis.ogg";

AVFormatContext* d_ctx = NULL;
AVCodec* d_codec = NULL;
AVCodecParameters* d_codec_params =  NULL;
int d_stream_index = -1;
AVFrame* d_frame  = NULL;

AVFormatContext* e_ctx = NULL;
AVCodec* e_codec = NULL;
AVCodecContext* e_codec_ctx = NULL;
AVStream* e_stream = NULL;
AVFrame* e_frame = NULL;


int sample_count = 0;
int sample_rate = 0;

int open_source()
{    
    d_ctx = avformat_alloc_context();
    int code = avformat_open_input(&d_ctx, source, NULL, NULL);  
    assert(code >= 0);
    code = avformat_find_stream_info(d_ctx, NULL);
    assert(code >= 0);

    for (int i = 0; i < d_ctx->nb_streams; ++i)
    {
        AVCodecParameters* local = d_ctx->streams[i]->codecpar;
        assert(local != NULL);
        if (local->codec_type == AVMEDIA_TYPE_AUDIO)
        {
            sample_rate = local->sample_rate;
            d_stream_index = i;
            d_codec_params = local;
            d_codec = avcodec_find_decoder(local->codec_id);
            assert(d_codec != NULL);
            av_dump_format(d_ctx,i, source, 0);
            return 0;
        }
    }    
    return code;    
}

int setup_encoder()
{
    /* allocate the output media context */
    int ret = avformat_alloc_output_context2(&e_ctx, NULL, NULL, destination);
    assert(ret >= 0);

    AVOutputFormat *fmt = e_ctx->oformat;
    if (fmt->audio_codec != AV_CODEC_ID_NONE)
    {
        e_codec = avcodec_find_encoder(fmt->audio_codec);
        e_stream = avformat_new_stream(e_ctx, NULL);
        e_stream->id = e_ctx->nb_streams - 1;
        e_codec_ctx = avcodec_alloc_context3(e_codec);
        e_codec_ctx->sample_fmt = d_codec_params->format;
        e_codec_ctx->bit_rate = d_codec_params->bit_rate;
        e_codec_ctx->sample_rate = d_codec_params->sample_rate;
        e_codec_ctx->channels = d_codec_params->channels;
        e_codec_ctx->channel_layout = d_codec_params->channel_layout;
        e_stream->time_base = (AVRational) {1, e_codec_ctx->sample_rate};
        if (e_ctx->oformat->flags & AVFMT_GLOBALHEADER)
        {
            e_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
        }

        ret = avcodec_open2(e_codec_ctx, e_codec, NULL);
        assert(ret >= 0);
        ret = avcodec_parameters_from_context(e_stream->codecpar, e_codec_ctx);
        assert(ret >= 0);

        av_dump_format(e_ctx, 0, destination, 1);
        ret = avio_open(&e_ctx->pb, destination, AVIO_FLAG_WRITE);
        assert(ret >= 0);

        int64_t sample_count = 0;
        e_frame = av_frame_alloc();
        e_frame->format = d_codec_params->format;
        e_frame->channel_layout = d_codec_params->channel_layout;
        e_frame->sample_rate = d_codec_params->sample_rate;
        e_frame->nb_samples = e_codec_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE ? 10000 : e_codec_ctx->frame_size;
        ret = av_frame_get_buffer(e_frame, 0);
        assert(ret >= 0);
    }
    return ret;
}

int encode()
{
    assert(e_frame);
    assert(e_ctx);
    assert(e_codec_ctx);
    AVPacket pkt = { NULL, 0, 0 }; // data and size must be 0;
    av_init_packet(&pkt);

    int code = av_frame_make_writable(e_frame);
    assert(code >= 0);
    e_frame->pts = av_rescale_q(sample_count, (AVRational){1, sample_rate}, e_codec_ctx->time_base);
    e_frame->data[0] = d_frame->data[0];

    int got_packet;
    code = avcodec_encode_audio2(e_codec_ctx, &pkt, e_frame, &got_packet);
    assert(code >= 0);
    if (got_packet == 1) {
        av_packet_rescale_ts(&pkt, e_codec_ctx->time_base, e_stream->time_base);
        pkt.stream_index = e_stream->index;
        code = av_interleaved_write_frame(e_ctx, &pkt);
        assert(code >= 0);
    }
    sample_count += d_frame->nb_samples;
    return code;
}

int main()
{

    int code = open_source();  
    assert(code >= 0);
    assert(d_ctx != NULL);
    assert(d_codec != NULL);
    assert(d_codec_params != NULL);
    AVCodecContext* d_codec_context = avcodec_alloc_context3(d_codec);
    assert(d_codec_context != NULL);
    code = avcodec_parameters_to_context(d_codec_context, d_codec_params);
    assert(code >= 0);
    code = avcodec_open2(d_codec_context, d_codec, NULL);
    assert(code >= 0);
    d_frame = av_frame_alloc();
    AVPacket* d_packet = av_packet_alloc();

    code = setup_encoder();
    assert(code >= 0);

    code = avformat_write_header(e_ctx, NULL);
    assert(code >= 0);

    // read raw packets from stream
    while (av_read_frame(d_ctx, d_packet) >= 0)
    {
        if (d_packet->stream_index == d_stream_index)
        {
            // send packet to decoder
            code = avcodec_send_packet(d_codec_context, d_packet);
            assert(code >= 0);
            while (code >= 0)
            {
                code = avcodec_receive_frame(d_codec_context, d_frame);
                if (code == AVERROR(EAGAIN) || code == AVERROR_EOF)
                {
                    break;
                }
                assert(code >= 0);
                encode();
            }
        }
        av_packet_unref(d_packet);
    }

    av_frame_free(&e_frame);
    return code;
}

### STDOUT ###

[jon@jon-desktop ffmpegtest]$ ./a.out
Input #0, ogg, from '/home/jon/Projects/Code/mediahandling/RegressionTests/ReferenceMedia/Audio/ogg/monotone.ogg':
  Duration: 00:00:03.00, start: 0.000000, bitrate: 23 kb/s
    Stream #0:0: Audio: vorbis, 44100 Hz, mono, fltp, 96 kb/s
Output #0, ogg, to '/tmp/vorbis.ogg':
    Stream #0:0: Audio: vorbis, 44100 Hz, mono, fltp, 96 kb/s

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Incorrect compressed audio

Andrew Randrianasulu
В сообщении от Sunday 26 January 2020 01:30:44 Jonathan Noble написал(а):

> Hi,
> I don't know why I am not getting a reply to my previous e-mails, so I am
> trying again. Please let me know if they were there.
>
> I have a pipeline of reader->decoder->encoder->writer where the codec
> parameters are the same on encoder and decoder.
> The resultant file has audio that is distorted and considerably shorter
> than the file that was being read from. There are no messages returned from
> ffmpeg to indicate anything going wrong.
>
> I've spent the last week looking into this and i've not got any further
> than at the start. Instead of posting my original code I thought i'd make a
> small representation of my code use ffmpeg calls only.
>
> What is it that I am missing? Are my e-mails getting through?

I can see your emails (so they arrive at Libav-user), but sadly can't help -
myself is only curious user

> Thanks in advance.
> Jon Noble
>
> ### The code ###
>
> #include <assert.h>
> #include <libavformat/avformat.h>
> #include <libavcodec/avcodec.h>
> #include <stdio.h>
>
> const char* source =
> "/home/jon/Projects/Code/mediahandling/RegressionTests/ReferenceMedia/Audio/ogg/monotone.ogg";
> const char* destination = "/tmp/vorbis.ogg";
>
> AVFormatContext* d_ctx = NULL;
> AVCodec* d_codec = NULL;
> AVCodecParameters* d_codec_params =  NULL;
> int d_stream_index = -1;
> AVFrame* d_frame  = NULL;
>
> AVFormatContext* e_ctx = NULL;
> AVCodec* e_codec = NULL;
> AVCodecContext* e_codec_ctx = NULL;
> AVStream* e_stream = NULL;
> AVFrame* e_frame = NULL;
>
>
> int sample_count = 0;
> int sample_rate = 0;
>
> int open_source()
> {
>     d_ctx = avformat_alloc_context();
>     int code = avformat_open_input(&d_ctx, source, NULL, NULL);
>     assert(code >= 0);
>     code = avformat_find_stream_info(d_ctx, NULL);
>     assert(code >= 0);
>
>     for (int i = 0; i < d_ctx->nb_streams; ++i)
>     {
>         AVCodecParameters* local = d_ctx->streams[i]->codecpar;
>         assert(local != NULL);
>         if (local->codec_type == AVMEDIA_TYPE_AUDIO)
>         {
>             sample_rate = local->sample_rate;
>             d_stream_index = i;
>             d_codec_params = local;
>             d_codec = avcodec_find_decoder(local->codec_id);
>             assert(d_codec != NULL);
>             av_dump_format(d_ctx,i, source, 0);
>             return 0;
>         }
>     }
>     return code;
> }
>
> int setup_encoder()
> {
>     /* allocate the output media context */
>     int ret = avformat_alloc_output_context2(&e_ctx, NULL, NULL,
> destination);
>     assert(ret >= 0);
>
>     AVOutputFormat *fmt = e_ctx->oformat;
>     if (fmt->audio_codec != AV_CODEC_ID_NONE)
>     {
>         e_codec = avcodec_find_encoder(fmt->audio_codec);
>         e_stream = avformat_new_stream(e_ctx, NULL);
>         e_stream->id = e_ctx->nb_streams - 1;
>         e_codec_ctx = avcodec_alloc_context3(e_codec);
>         e_codec_ctx->sample_fmt = d_codec_params->format;
>         e_codec_ctx->bit_rate = d_codec_params->bit_rate;
>         e_codec_ctx->sample_rate = d_codec_params->sample_rate;
>         e_codec_ctx->channels = d_codec_params->channels;
>         e_codec_ctx->channel_layout = d_codec_params->channel_layout;
>         e_stream->time_base = (AVRational) {1, e_codec_ctx->sample_rate};
>         if (e_ctx->oformat->flags & AVFMT_GLOBALHEADER)
>         {
>             e_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
>         }
>
>         ret = avcodec_open2(e_codec_ctx, e_codec, NULL);
>         assert(ret >= 0);
>         ret = avcodec_parameters_from_context(e_stream->codecpar,
> e_codec_ctx);
>         assert(ret >= 0);
>
>         av_dump_format(e_ctx, 0, destination, 1);
>         ret = avio_open(&e_ctx->pb, destination, AVIO_FLAG_WRITE);
>         assert(ret >= 0);
>
>         int64_t sample_count = 0;
>         e_frame = av_frame_alloc();
>         e_frame->format = d_codec_params->format;
>         e_frame->channel_layout = d_codec_params->channel_layout;
>         e_frame->sample_rate = d_codec_params->sample_rate;
>         e_frame->nb_samples = e_codec_ctx->codec->capabilities &
> AV_CODEC_CAP_VARIABLE_FRAME_SIZE ? 10000 : e_codec_ctx->frame_size;
>         ret = av_frame_get_buffer(e_frame, 0);
>         assert(ret >= 0);
>     }
>     return ret;
> }
>
> int encode()
> {
>     assert(e_frame);
>     assert(e_ctx);
>     assert(e_codec_ctx);
>     AVPacket pkt = { NULL, 0, 0 }; // data and size must be 0;
>     av_init_packet(&pkt);
>
>     int code = av_frame_make_writable(e_frame);
>     assert(code >= 0);
>     e_frame->pts = av_rescale_q(sample_count, (AVRational){1, sample_rate},
> e_codec_ctx->time_base);
>     e_frame->data[0] = d_frame->data[0];
>
>     int got_packet;
>     code = avcodec_encode_audio2(e_codec_ctx, &pkt, e_frame, &got_packet);
>     assert(code >= 0);
>     if (got_packet == 1) {
>         av_packet_rescale_ts(&pkt, e_codec_ctx->time_base,
> e_stream->time_base);
>         pkt.stream_index = e_stream->index;
>         code = av_interleaved_write_frame(e_ctx, &pkt);
>         assert(code >= 0);
>     }
>     sample_count += d_frame->nb_samples;
>     return code;
> }
>
> int main()
> {
>
>     int code = open_source();
>     assert(code >= 0);
>     assert(d_ctx != NULL);
>     assert(d_codec != NULL);
>     assert(d_codec_params != NULL);
>     AVCodecContext* d_codec_context = avcodec_alloc_context3(d_codec);
>     assert(d_codec_context != NULL);
>     code = avcodec_parameters_to_context(d_codec_context, d_codec_params);
>     assert(code >= 0);
>     code = avcodec_open2(d_codec_context, d_codec, NULL);
>     assert(code >= 0);
>     d_frame = av_frame_alloc();
>     AVPacket* d_packet = av_packet_alloc();
>
>     code = setup_encoder();
>     assert(code >= 0);
>
>     code = avformat_write_header(e_ctx, NULL);
>     assert(code >= 0);
>
>     // read raw packets from stream
>     while (av_read_frame(d_ctx, d_packet) >= 0)
>     {
>         if (d_packet->stream_index == d_stream_index)
>         {
>             // send packet to decoder
>             code = avcodec_send_packet(d_codec_context, d_packet);
>             assert(code >= 0);
>             while (code >= 0)
>             {
>                 code = avcodec_receive_frame(d_codec_context, d_frame);
>                 if (code == AVERROR(EAGAIN) || code == AVERROR_EOF)
>                 {
>                     break;
>                 }
>                 assert(code >= 0);
>                 encode();
>             }
>         }
>         av_packet_unref(d_packet);
>     }
>
>     av_frame_free(&e_frame);
>     return code;
> }
>
> ### STDOUT ###
>
> [jon@jon-desktop ffmpegtest]$ ./a.out
> Input #0, ogg, from
> '/home/jon/Projects/Code/mediahandling/RegressionTests/ReferenceMedia/Audio/ogg/monotone.ogg':
>   Duration: 00:00:03.00, start: 0.000000, bitrate: 23 kb/s
>     Stream #0:0: Audio: vorbis, 44100 Hz, mono, fltp, 96 kb/s
> Output #0, ogg, to '/tmp/vorbis.ogg':
>     Stream #0:0: Audio: vorbis, 44100 Hz, mono, fltp, 96 kb/s
>


_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Incorrect compressed audio

Jonathan Noble


On Sun, 26 Jan 2020 at 02:56, Andrew Randrianasulu <[hidden email]> wrote:
В сообщении от Sunday 26 January 2020 01:30:44 Jonathan Noble написал(а):
> Hi,
> I don't know why I am not getting a reply to my previous e-mails, so I am
> trying again. Please let me know if they were there.
>
> I have a pipeline of reader->decoder->encoder->writer where the codec
> parameters are the same on encoder and decoder.
> The resultant file has audio that is distorted and considerably shorter
> than the file that was being read from. There are no messages returned from
> ffmpeg to indicate anything going wrong.
>
> I've spent the last week looking into this and i've not got any further
> than at the start. Instead of posting my original code I thought i'd make a
> small representation of my code use ffmpeg calls only.
>
> What is it that I am missing? Are my e-mails getting through?

I can see your emails (so they arrive at Libav-user), but sadly can't help -
myself is only curious user
Thanks. I wondered what was going on. I guess this question joins the countless many in this ML that effectively is piped to /dev/null
Off to bang my head against the wall with ffmpeg libs, again.
 

> Thanks in advance.
> Jon Noble
>
> ### The code ###
>
> #include <assert.h>
> #include <libavformat/avformat.h>
> #include <libavcodec/avcodec.h>
> #include <stdio.h>
>
> const char* source =
> "/home/jon/Projects/Code/mediahandling/RegressionTests/ReferenceMedia/Audio/ogg/monotone.ogg";
> const char* destination = "/tmp/vorbis.ogg";
>
> AVFormatContext* d_ctx = NULL;
> AVCodec* d_codec = NULL;
> AVCodecParameters* d_codec_params =  NULL;
> int d_stream_index = -1;
> AVFrame* d_frame  = NULL;
>
> AVFormatContext* e_ctx = NULL;
> AVCodec* e_codec = NULL;
> AVCodecContext* e_codec_ctx = NULL;
> AVStream* e_stream = NULL;
> AVFrame* e_frame = NULL;
>
>
> int sample_count = 0;
> int sample_rate = 0;
>
> int open_source()
> {
>     d_ctx = avformat_alloc_context();
>     int code = avformat_open_input(&d_ctx, source, NULL, NULL);
>     assert(code >= 0);
>     code = avformat_find_stream_info(d_ctx, NULL);
>     assert(code >= 0);
>
>     for (int i = 0; i < d_ctx->nb_streams; ++i)
>     {
>         AVCodecParameters* local = d_ctx->streams[i]->codecpar;
>         assert(local != NULL);
>         if (local->codec_type == AVMEDIA_TYPE_AUDIO)
>         {
>             sample_rate = local->sample_rate;
>             d_stream_index = i;
>             d_codec_params = local;
>             d_codec = avcodec_find_decoder(local->codec_id);
>             assert(d_codec != NULL);
>             av_dump_format(d_ctx,i, source, 0);
>             return 0;
>         }
>     }
>     return code;
> }
>
> int setup_encoder()
> {
>     /* allocate the output media context */
>     int ret = avformat_alloc_output_context2(&e_ctx, NULL, NULL,
> destination);
>     assert(ret >= 0);
>
>     AVOutputFormat *fmt = e_ctx->oformat;
>     if (fmt->audio_codec != AV_CODEC_ID_NONE)
>     {
>         e_codec = avcodec_find_encoder(fmt->audio_codec);
>         e_stream = avformat_new_stream(e_ctx, NULL);
>         e_stream->id = e_ctx->nb_streams - 1;
>         e_codec_ctx = avcodec_alloc_context3(e_codec);
>         e_codec_ctx->sample_fmt = d_codec_params->format;
>         e_codec_ctx->bit_rate = d_codec_params->bit_rate;
>         e_codec_ctx->sample_rate = d_codec_params->sample_rate;
>         e_codec_ctx->channels = d_codec_params->channels;
>         e_codec_ctx->channel_layout = d_codec_params->channel_layout;
>         e_stream->time_base = (AVRational) {1, e_codec_ctx->sample_rate};
>         if (e_ctx->oformat->flags & AVFMT_GLOBALHEADER)
>         {
>             e_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
>         }
>
>         ret = avcodec_open2(e_codec_ctx, e_codec, NULL);
>         assert(ret >= 0);
>         ret = avcodec_parameters_from_context(e_stream->codecpar,
> e_codec_ctx);
>         assert(ret >= 0);
>
>         av_dump_format(e_ctx, 0, destination, 1);
>         ret = avio_open(&e_ctx->pb, destination, AVIO_FLAG_WRITE);
>         assert(ret >= 0);
>
>         int64_t sample_count = 0;
>         e_frame = av_frame_alloc();
>         e_frame->format = d_codec_params->format;
>         e_frame->channel_layout = d_codec_params->channel_layout;
>         e_frame->sample_rate = d_codec_params->sample_rate;
>         e_frame->nb_samples = e_codec_ctx->codec->capabilities &
> AV_CODEC_CAP_VARIABLE_FRAME_SIZE ? 10000 : e_codec_ctx->frame_size;
>         ret = av_frame_get_buffer(e_frame, 0);
>         assert(ret >= 0);
>     }
>     return ret;
> }
>
> int encode()
> {
>     assert(e_frame);
>     assert(e_ctx);
>     assert(e_codec_ctx);
>     AVPacket pkt = { NULL, 0, 0 }; // data and size must be 0;
>     av_init_packet(&pkt);
>
>     int code = av_frame_make_writable(e_frame);
>     assert(code >= 0);
>     e_frame->pts = av_rescale_q(sample_count, (AVRational){1, sample_rate},
> e_codec_ctx->time_base);
>     e_frame->data[0] = d_frame->data[0];
>
>     int got_packet;
>     code = avcodec_encode_audio2(e_codec_ctx, &pkt, e_frame, &got_packet);
>     assert(code >= 0);
>     if (got_packet == 1) {
>         av_packet_rescale_ts(&pkt, e_codec_ctx->time_base,
> e_stream->time_base);
>         pkt.stream_index = e_stream->index;
>         code = av_interleaved_write_frame(e_ctx, &pkt);
>         assert(code >= 0);
>     }
>     sample_count += d_frame->nb_samples;
>     return code;
> }
>
> int main()
> {
>
>     int code = open_source();
>     assert(code >= 0);
>     assert(d_ctx != NULL);
>     assert(d_codec != NULL);
>     assert(d_codec_params != NULL);
>     AVCodecContext* d_codec_context = avcodec_alloc_context3(d_codec);
>     assert(d_codec_context != NULL);
>     code = avcodec_parameters_to_context(d_codec_context, d_codec_params);
>     assert(code >= 0);
>     code = avcodec_open2(d_codec_context, d_codec, NULL);
>     assert(code >= 0);
>     d_frame = av_frame_alloc();
>     AVPacket* d_packet = av_packet_alloc();
>
>     code = setup_encoder();
>     assert(code >= 0);
>
>     code = avformat_write_header(e_ctx, NULL);
>     assert(code >= 0);
>
>     // read raw packets from stream
>     while (av_read_frame(d_ctx, d_packet) >= 0)
>     {
>         if (d_packet->stream_index == d_stream_index)
>         {
>             // send packet to decoder
>             code = avcodec_send_packet(d_codec_context, d_packet);
>             assert(code >= 0);
>             while (code >= 0)
>             {
>                 code = avcodec_receive_frame(d_codec_context, d_frame);
>                 if (code == AVERROR(EAGAIN) || code == AVERROR_EOF)
>                 {
>                     break;
>                 }
>                 assert(code >= 0);
>                 encode();
>             }
>         }
>         av_packet_unref(d_packet);
>     }
>
>     av_frame_free(&e_frame);
>     return code;
> }
>
> ### STDOUT ###
>
> [jon@jon-desktop ffmpegtest]$ ./a.out
> Input #0, ogg, from
> '/home/jon/Projects/Code/mediahandling/RegressionTests/ReferenceMedia/Audio/ogg/monotone.ogg':
>   Duration: 00:00:03.00, start: 0.000000, bitrate: 23 kb/s
>     Stream #0:0: Audio: vorbis, 44100 Hz, mono, fltp, 96 kb/s
> Output #0, ogg, to '/tmp/vorbis.ogg':
>     Stream #0:0: Audio: vorbis, 44100 Hz, mono, fltp, 96 kb/s
>


_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Incorrect compressed audio

Leandro Moreira
In reply to this post by Jonathan Noble
Hi there,

I think that the transcoder example provided by ffmpeg works as well as some community sample code.


On Sat, Jan 25, 2020 at 7:31 PM Jonathan Noble <[hidden email]> wrote:
Hi,
I don't know why I am not getting a reply to my previous e-mails, so I am trying again. Please let me know if they were there.

I have a pipeline of reader->decoder->encoder->writer where the codec parameters are the same on encoder and decoder.
The resultant file has audio that is distorted and considerably shorter than the file that was being read from. There are no messages returned from ffmpeg to indicate anything going wrong.

I've spent the last week looking into this and i've not got any further than at the start. Instead of posting my original code I thought i'd make a small representation of my code use ffmpeg calls only.

What is it that I am missing? Are my e-mails getting through?
Thanks in advance.
Jon Noble

### The code ###

#include <assert.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <stdio.h>

const char* source = "/home/jon/Projects/Code/mediahandling/RegressionTests/ReferenceMedia/Audio/ogg/monotone.ogg";
const char* destination = "/tmp/vorbis.ogg";

AVFormatContext* d_ctx = NULL;
AVCodec* d_codec = NULL;
AVCodecParameters* d_codec_params =  NULL;
int d_stream_index = -1;
AVFrame* d_frame  = NULL;

AVFormatContext* e_ctx = NULL;
AVCodec* e_codec = NULL;
AVCodecContext* e_codec_ctx = NULL;
AVStream* e_stream = NULL;
AVFrame* e_frame = NULL;


int sample_count = 0;
int sample_rate = 0;

int open_source()
{    
    d_ctx = avformat_alloc_context();
    int code = avformat_open_input(&d_ctx, source, NULL, NULL);  
    assert(code >= 0);
    code = avformat_find_stream_info(d_ctx, NULL);
    assert(code >= 0);

    for (int i = 0; i < d_ctx->nb_streams; ++i)
    {
        AVCodecParameters* local = d_ctx->streams[i]->codecpar;
        assert(local != NULL);
        if (local->codec_type == AVMEDIA_TYPE_AUDIO)
        {
            sample_rate = local->sample_rate;
            d_stream_index = i;
            d_codec_params = local;
            d_codec = avcodec_find_decoder(local->codec_id);
            assert(d_codec != NULL);
            av_dump_format(d_ctx,i, source, 0);
            return 0;
        }
    }    
    return code;    
}

int setup_encoder()
{
    /* allocate the output media context */
    int ret = avformat_alloc_output_context2(&e_ctx, NULL, NULL, destination);
    assert(ret >= 0);

    AVOutputFormat *fmt = e_ctx->oformat;
    if (fmt->audio_codec != AV_CODEC_ID_NONE)
    {
        e_codec = avcodec_find_encoder(fmt->audio_codec);
        e_stream = avformat_new_stream(e_ctx, NULL);
        e_stream->id = e_ctx->nb_streams - 1;
        e_codec_ctx = avcodec_alloc_context3(e_codec);
        e_codec_ctx->sample_fmt = d_codec_params->format;
        e_codec_ctx->bit_rate = d_codec_params->bit_rate;
        e_codec_ctx->sample_rate = d_codec_params->sample_rate;
        e_codec_ctx->channels = d_codec_params->channels;
        e_codec_ctx->channel_layout = d_codec_params->channel_layout;
        e_stream->time_base = (AVRational) {1, e_codec_ctx->sample_rate};
        if (e_ctx->oformat->flags & AVFMT_GLOBALHEADER)
        {
            e_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
        }

        ret = avcodec_open2(e_codec_ctx, e_codec, NULL);
        assert(ret >= 0);
        ret = avcodec_parameters_from_context(e_stream->codecpar, e_codec_ctx);
        assert(ret >= 0);

        av_dump_format(e_ctx, 0, destination, 1);
        ret = avio_open(&e_ctx->pb, destination, AVIO_FLAG_WRITE);
        assert(ret >= 0);

        int64_t sample_count = 0;
        e_frame = av_frame_alloc();
        e_frame->format = d_codec_params->format;
        e_frame->channel_layout = d_codec_params->channel_layout;
        e_frame->sample_rate = d_codec_params->sample_rate;
        e_frame->nb_samples = e_codec_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE ? 10000 : e_codec_ctx->frame_size;
        ret = av_frame_get_buffer(e_frame, 0);
        assert(ret >= 0);
    }
    return ret;
}

int encode()
{
    assert(e_frame);
    assert(e_ctx);
    assert(e_codec_ctx);
    AVPacket pkt = { NULL, 0, 0 }; // data and size must be 0;
    av_init_packet(&pkt);

    int code = av_frame_make_writable(e_frame);
    assert(code >= 0);
    e_frame->pts = av_rescale_q(sample_count, (AVRational){1, sample_rate}, e_codec_ctx->time_base);
    e_frame->data[0] = d_frame->data[0];

    int got_packet;
    code = avcodec_encode_audio2(e_codec_ctx, &pkt, e_frame, &got_packet);
    assert(code >= 0);
    if (got_packet == 1) {
        av_packet_rescale_ts(&pkt, e_codec_ctx->time_base, e_stream->time_base);
        pkt.stream_index = e_stream->index;
        code = av_interleaved_write_frame(e_ctx, &pkt);
        assert(code >= 0);
    }
    sample_count += d_frame->nb_samples;
    return code;
}

int main()
{

    int code = open_source();  
    assert(code >= 0);
    assert(d_ctx != NULL);
    assert(d_codec != NULL);
    assert(d_codec_params != NULL);
    AVCodecContext* d_codec_context = avcodec_alloc_context3(d_codec);
    assert(d_codec_context != NULL);
    code = avcodec_parameters_to_context(d_codec_context, d_codec_params);
    assert(code >= 0);
    code = avcodec_open2(d_codec_context, d_codec, NULL);
    assert(code >= 0);
    d_frame = av_frame_alloc();
    AVPacket* d_packet = av_packet_alloc();

    code = setup_encoder();
    assert(code >= 0);

    code = avformat_write_header(e_ctx, NULL);
    assert(code >= 0);

    // read raw packets from stream
    while (av_read_frame(d_ctx, d_packet) >= 0)
    {
        if (d_packet->stream_index == d_stream_index)
        {
            // send packet to decoder
            code = avcodec_send_packet(d_codec_context, d_packet);
            assert(code >= 0);
            while (code >= 0)
            {
                code = avcodec_receive_frame(d_codec_context, d_frame);
                if (code == AVERROR(EAGAIN) || code == AVERROR_EOF)
                {
                    break;
                }
                assert(code >= 0);
                encode();
            }
        }
        av_packet_unref(d_packet);
    }

    av_frame_free(&e_frame);
    return code;
}

### STDOUT ###

[jon@jon-desktop ffmpegtest]$ ./a.out
Input #0, ogg, from '/home/jon/Projects/Code/mediahandling/RegressionTests/ReferenceMedia/Audio/ogg/monotone.ogg':
  Duration: 00:00:03.00, start: 0.000000, bitrate: 23 kb/s
    Stream #0:0: Audio: vorbis, 44100 Hz, mono, fltp, 96 kb/s
Output #0, ogg, to '/tmp/vorbis.ogg':
    Stream #0:0: Audio: vorbis, 44100 Hz, mono, fltp, 96 kb/s
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Incorrect compressed audio

Jonathan Noble


On Tue, 28 Jan 2020 at 00:12, Leandro Moreira <[hidden email]> wrote:
Hi there,

I think that the transcoder example provided by ffmpeg works as well as some community sample code.

Thanks. Those are the ones I've been referring to, amongst countless others, so far. I'll have a read through them again or try my encoding stage with a definite known input (create samples in code to replicate a sinewave or silence).

On Sat, Jan 25, 2020 at 7:31 PM Jonathan Noble <[hidden email]> wrote:
Hi,
I don't know why I am not getting a reply to my previous e-mails, so I am trying again. Please let me know if they were there.

I have a pipeline of reader->decoder->encoder->writer where the codec parameters are the same on encoder and decoder.
The resultant file has audio that is distorted and considerably shorter than the file that was being read from. There are no messages returned from ffmpeg to indicate anything going wrong.

I've spent the last week looking into this and i've not got any further than at the start. Instead of posting my original code I thought i'd make a small representation of my code use ffmpeg calls only.

What is it that I am missing? Are my e-mails getting through?
Thanks in advance.
Jon Noble

### The code ###

#include <assert.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <stdio.h>

const char* source = "/home/jon/Projects/Code/mediahandling/RegressionTests/ReferenceMedia/Audio/ogg/monotone.ogg";
const char* destination = "/tmp/vorbis.ogg";

AVFormatContext* d_ctx = NULL;
AVCodec* d_codec = NULL;
AVCodecParameters* d_codec_params =  NULL;
int d_stream_index = -1;
AVFrame* d_frame  = NULL;

AVFormatContext* e_ctx = NULL;
AVCodec* e_codec = NULL;
AVCodecContext* e_codec_ctx = NULL;
AVStream* e_stream = NULL;
AVFrame* e_frame = NULL;


int sample_count = 0;
int sample_rate = 0;

int open_source()
{    
    d_ctx = avformat_alloc_context();
    int code = avformat_open_input(&d_ctx, source, NULL, NULL);  
    assert(code >= 0);
    code = avformat_find_stream_info(d_ctx, NULL);
    assert(code >= 0);

    for (int i = 0; i < d_ctx->nb_streams; ++i)
    {
        AVCodecParameters* local = d_ctx->streams[i]->codecpar;
        assert(local != NULL);
        if (local->codec_type == AVMEDIA_TYPE_AUDIO)
        {
            sample_rate = local->sample_rate;
            d_stream_index = i;
            d_codec_params = local;
            d_codec = avcodec_find_decoder(local->codec_id);
            assert(d_codec != NULL);
            av_dump_format(d_ctx,i, source, 0);
            return 0;
        }
    }    
    return code;    
}

int setup_encoder()
{
    /* allocate the output media context */
    int ret = avformat_alloc_output_context2(&e_ctx, NULL, NULL, destination);
    assert(ret >= 0);

    AVOutputFormat *fmt = e_ctx->oformat;
    if (fmt->audio_codec != AV_CODEC_ID_NONE)
    {
        e_codec = avcodec_find_encoder(fmt->audio_codec);
        e_stream = avformat_new_stream(e_ctx, NULL);
        e_stream->id = e_ctx->nb_streams - 1;
        e_codec_ctx = avcodec_alloc_context3(e_codec);
        e_codec_ctx->sample_fmt = d_codec_params->format;
        e_codec_ctx->bit_rate = d_codec_params->bit_rate;
        e_codec_ctx->sample_rate = d_codec_params->sample_rate;
        e_codec_ctx->channels = d_codec_params->channels;
        e_codec_ctx->channel_layout = d_codec_params->channel_layout;
        e_stream->time_base = (AVRational) {1, e_codec_ctx->sample_rate};
        if (e_ctx->oformat->flags & AVFMT_GLOBALHEADER)
        {
            e_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
        }

        ret = avcodec_open2(e_codec_ctx, e_codec, NULL);
        assert(ret >= 0);
        ret = avcodec_parameters_from_context(e_stream->codecpar, e_codec_ctx);
        assert(ret >= 0);

        av_dump_format(e_ctx, 0, destination, 1);
        ret = avio_open(&e_ctx->pb, destination, AVIO_FLAG_WRITE);
        assert(ret >= 0);

        int64_t sample_count = 0;
        e_frame = av_frame_alloc();
        e_frame->format = d_codec_params->format;
        e_frame->channel_layout = d_codec_params->channel_layout;
        e_frame->sample_rate = d_codec_params->sample_rate;
        e_frame->nb_samples = e_codec_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE ? 10000 : e_codec_ctx->frame_size;
        ret = av_frame_get_buffer(e_frame, 0);
        assert(ret >= 0);
    }
    return ret;
}

int encode()
{
    assert(e_frame);
    assert(e_ctx);
    assert(e_codec_ctx);
    AVPacket pkt = { NULL, 0, 0 }; // data and size must be 0;
    av_init_packet(&pkt);

    int code = av_frame_make_writable(e_frame);
    assert(code >= 0);
    e_frame->pts = av_rescale_q(sample_count, (AVRational){1, sample_rate}, e_codec_ctx->time_base);
    e_frame->data[0] = d_frame->data[0];

    int got_packet;
    code = avcodec_encode_audio2(e_codec_ctx, &pkt, e_frame, &got_packet);
    assert(code >= 0);
    if (got_packet == 1) {
        av_packet_rescale_ts(&pkt, e_codec_ctx->time_base, e_stream->time_base);
        pkt.stream_index = e_stream->index;
        code = av_interleaved_write_frame(e_ctx, &pkt);
        assert(code >= 0);
    }
    sample_count += d_frame->nb_samples;
    return code;
}

int main()
{

    int code = open_source();  
    assert(code >= 0);
    assert(d_ctx != NULL);
    assert(d_codec != NULL);
    assert(d_codec_params != NULL);
    AVCodecContext* d_codec_context = avcodec_alloc_context3(d_codec);
    assert(d_codec_context != NULL);
    code = avcodec_parameters_to_context(d_codec_context, d_codec_params);
    assert(code >= 0);
    code = avcodec_open2(d_codec_context, d_codec, NULL);
    assert(code >= 0);
    d_frame = av_frame_alloc();
    AVPacket* d_packet = av_packet_alloc();

    code = setup_encoder();
    assert(code >= 0);

    code = avformat_write_header(e_ctx, NULL);
    assert(code >= 0);

    // read raw packets from stream
    while (av_read_frame(d_ctx, d_packet) >= 0)
    {
        if (d_packet->stream_index == d_stream_index)
        {
            // send packet to decoder
            code = avcodec_send_packet(d_codec_context, d_packet);
            assert(code >= 0);
            while (code >= 0)
            {
                code = avcodec_receive_frame(d_codec_context, d_frame);
                if (code == AVERROR(EAGAIN) || code == AVERROR_EOF)
                {
                    break;
                }
                assert(code >= 0);
                encode();
            }
        }
        av_packet_unref(d_packet);
    }

    av_frame_free(&e_frame);
    return code;
}

### STDOUT ###

[jon@jon-desktop ffmpegtest]$ ./a.out
Input #0, ogg, from '/home/jon/Projects/Code/mediahandling/RegressionTests/ReferenceMedia/Audio/ogg/monotone.ogg':
  Duration: 00:00:03.00, start: 0.000000, bitrate: 23 kb/s
    Stream #0:0: Audio: vorbis, 44100 Hz, mono, fltp, 96 kb/s
Output #0, ogg, to '/tmp/vorbis.ogg':
    Stream #0:0: Audio: vorbis, 44100 Hz, mono, fltp, 96 kb/s
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Incorrect compressed audio

Gonzalo Garramuño


On 28/1/20 06:49, Jonathan Noble wrote:


On Tue, 28 Jan 2020 at 00:12, Leandro Moreira <[hidden email]> wrote:
Hi there,

I think that the transcoder example provided by ffmpeg works as well as some community sample code.

Thanks. Those are the ones I've been referring to, amongst countless others, so far. I'll have a read through them again or try my encoding stage with a definite known input (create samples in code to replicate a sinewave or silence).

You should start by using those examples *EXACTLY* as written.  Your code shows some issues:  you don't have e_frame->channels set to anything, you don't call av_write_trailer(), etc.  With those two changes and loading/saving out .aac audio, I was able to write it out properly (but it would sometimes fail with a warning about Inf/Nan values, which means I did not fix all errors in your code -- and thus why I have not posted my changes).

-- 
Gonzalo Garramuño

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".