[Libav-user] Incorrect compressed audio

Jonathan Noble jonnobleuk at gmail.com
Sun Jan 26 00:30:44 EET 2020


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 at 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20200125/81a97685/attachment.html>


More information about the Libav-user mailing list