4
votes

I am trying to decode opus using libavcodec. I am able to do it using libopus library alone. But I am trying to acheive same using libavcodec. I am trying to figure it out Why its not working in my case. I have an rtp stream and trying to decode it. The result in decoded packet is same as input. Decoded frame normally contain pcm values instead of that Im receving opus frame that actually I send. Please help me.

av_register_all();
avcodec_register_all();
AVCodec *codec;
AVCodecContext *c = NULL;
AVPacket avpkt;
AVFrame *decoded_frame = NULL;
av_init_packet(&avpkt);
codec = avcodec_find_decoder(AV_CODEC_ID_OPUS);
if (!codec) {
     printf("Codec not found\n");
     exit(1);
}
c = avcodec_alloc_context3(codec);
if (!c) {
   printf("Could not allocate audio codec context\n");
   exit(1);
}
/* put sample parameters */
c->sample_rate = 48000;
c->request_sample_fmt = AV_SAMPLE_FMT_FLT;
c->channels = 2;
/* open it */
if (avcodec_open2(c, codec, NULL) < 0) {
    printf("Could not open codec\n");
    exit(1);
}

AVPacket avpkt;
AVFrame *decoded_frame = NULL;
av_init_packet(&avpkt);
avpkt.data = Buffer;  // Buffer is packet data here
avpkt.size = len;    // length of the packet
int i, ch;

if (!decoded_frame) {
    if (!(decoded_frame = av_frame_alloc())) {
        RELAY_SERVER_PRINT("Could not allocate audio frame\n");
        exit(1);
    }
}
int ret;
int got_frame = 0;
ret = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt);
if (ret < 0) {
        fprintf(stderr, "Error decoding audio frame (%s)\n", av_err2str(ret));
        return ret;
    }
printf("length %i\n", decoded_frame->pkt_size);
1
What specifically goes wrong? Does the init step fail? Or the decode step? Or do all calls succeed but the audio data doesn't sound correctly? How did you test that? Did you run the RTP data through a RTP payload parser before serving the data as input to the decoder? Do you get any messages on the stderr while running your code?Ronald S. Bultje
I did parse the RTP . In Buffer its only the OPUS packet. I have a parallel working with opus_decode from liboupus its working ok. But using libavcodec its not. The main problem it does not produce any error. The init or nothing fails. The avcodec_decode_audio4 returns me a frame that has packet size of my opus packet that was send for decoding. I do not get any error message. Thats main problem.Abu
Is the "client_sockt_num_1" in avcodec_decode_audio4() a typo?Ronald S. Bultje
yes it was typo when I pasted here,Abu
Is got_frame actually 1? In some cases, got_frame can be zero, which means it's still ingesting audio data and there is not yet any output...Ronald S. Bultje

1 Answers

3
votes

I had the same problem. My stream was encoded with 8kHz and ffmpeg is always initializing libopus with 48kHz (hard-coded).

See ffmpeg code snippet:

static av_cold int libopus_decode_init(AVCodecContext *avc)
{
    (...)
    avc->sample_rate    = 48000;
    avc->sample_fmt     = avc->request_sample_fmt == AV_SAMPLE_FMT_FLT ?
                          AV_SAMPLE_FMT_FLT : AV_SAMPLE_FMT_S16;
    (...)  
}

I've replaced that by:

if (avc->sample_rate == 0)
    avc->sample_rate = 48000;

and decoding works now. I wonder if this decoder supports dynamic bitrate changes.

The length of the raw frame has to be calculated by:

int frame_size = decoded_frame->nb_samples * av_get_bytes_per_sample(decoded_frame->sample_fmt);