avcodec_open2:PCM 通道越界

bot*_*357 2 ffmpeg rtp libav

我正在尝试在我的应用程序中读取音频 RTP 流,但出现此错误:

[pcm_mulaw @ 03390580] PCM channels out of bounds
Run Code Online (Sandbox Code Playgroud)

我可以用 ffplay 很好地读取 RTP 流:

ffplay -i test.sdp -protocol_whitelist file,udp,rtp
Run Code Online (Sandbox Code Playgroud)

我使用以下命令生成 RTP 流:

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
Run Code Online (Sandbox Code Playgroud)

这是我的源代码:

#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)
Run Code Online (Sandbox Code Playgroud)

我知道有些不对劲,但那是什么?非常感谢建议和提示。

bot*_*357 5

我发现流属性不是自动设置的,所以我必须在调用之前手动设置它们avcodec_open2()

inCodecCtx->sample_rate = 8000;
inCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
inCodecCtx->channels = 1;
inCodecCtx->channel_layout = AV_CH_LAYOUT_MONO;
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助遇到与我相同问题的人。