Search code examples
ffmpegrtplibav

avcodec_open2: PCM channels out of bounds


I am trying to read an audio RTP stream in my application, but I am getting this error:

[pcm_mulaw @ 03390580] PCM channels out of bounds

I can read the RTP stream fine with ffplay:

ffplay -i test.sdp -protocol_whitelist file,udp,rtp

I generate the RTP stream using this command:

ffmpeg -re -f lavfi -i aevalsrc="sin(400*2*PI*t)" -ar 8000 -f mulaw -f rtp rtp://127.0.0.1:8554

// SDP
v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 127.0.0.1
t=0 0
a=tool:libavformat 57.25.101
m=audio 8554 RTP/AVP 0
b=AS:64

And here is my source code:

#include "stdafx.h"
#include <math.h>
extern "C"
{
    #include <libavutil/opt.h>
    #include <libavcodec/avcodec.h>
    #include <libavutil/channel_layout.h>
    #include <libavutil/common.h>
    #include <libavutil/imgutils.h>
    #include <libavutil/mathematics.h>
    #include <libavutil/samplefmt.h>
    #include <libavformat/avformat.h>
}

#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096

#define ERRBUFFLEN 200
char errbuf[ERRBUFFLEN];
#define av_err2str(ret) av_strerror(ret, errbuf, ERRBUFFLEN)

/*
* Audio decoding.
*/
static void audio_decode_example(const char *outfilename, const char *filename)
{
    AVCodec *inCodec;
    AVCodecContext *inCodecCtx = NULL;
    int len;
    FILE *f, *outfile;
    uint8_t inbuf[AUDIO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
    AVPacket avpkt;
    AVFrame *decoded_frame = NULL;


    AVFormatContext *inFormatCtx = NULL;
    AVFrame *inFrame = NULL;
    AVFrame *outFrame = NULL;

    int ret;

    av_init_packet(&avpkt);

    AVDictionary *d = NULL;           // "create" an empty dictionary
    int listen = false;
    listen = true;
    if (listen)
    {
        av_dict_set(&d, "protocol_whitelist", "file,udp,rtp", 0); // add an entry
        printf("Listening mode.\n");
    }
    else {
        printf("Connecting mode.\n");
    }

    // Open video file
    ret = avformat_open_input(&inFormatCtx, filename, NULL, &d);
    if (ret <0)
    {
        printf_s("Failed: cannot open input.\n");
        av_strerror(ret, errbuf, ERRBUFFLEN);
        fprintf(stderr, "avformat_open_input() fail: %s\n", errbuf);
        exit(1);
    }

    printf_s("Retrieve stream information.\n");
    ret = avformat_find_stream_info(inFormatCtx, NULL);
    if (ret <0)
    {
        printf_s("Failed: cannot find stream.\n");
        av_strerror(ret, errbuf, ERRBUFFLEN);
        fprintf(stderr, "avformat_find_stream_info() fail: %s\n", errbuf);
        exit(1);
    }

    av_dump_format(inFormatCtx, 0, filename, 0);

    int stream_idx = -1;

    for (int i = 0; i < inFormatCtx->nb_streams; i++)
        if (inFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
            stream_idx = i;
            break;
        }
    if (stream_idx == -1)
    {
        fprintf(stderr, "Video stream not found\n");
        exit(1);
    }

    inCodec = avcodec_find_decoder(inFormatCtx->streams[stream_idx]->codec->codec_id);
    if (!inCodec) {
        fprintf(stderr, "Codec not found\n");
        exit(1);
    }

    inCodecCtx = avcodec_alloc_context3(inCodec);
    if (!inCodecCtx) {
        fprintf(stderr, "Could not allocate audio codec context\n");
        exit(1);
    }
    /* Error here */
    ret = avcodec_open2(inCodecCtx, inCodec, NULL);
    if (ret < 0) {
        fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
        exit(1);
    }
    (...more code)

I know something is wrong, but what is it? Suggestions and tips are much appreciated.


Solution

  • I found out that the stream attributes were not set automatically, so I had to manually set them before calling avcodec_open2():

    inCodecCtx->sample_rate = 8000;
    inCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
    inCodecCtx->channels = 1;
    inCodecCtx->channel_layout = AV_CH_LAYOUT_MONO;
    

    Hope this helps someone who encountered the same issue as I do.