#include "bytestream.h"
#include "internal.h"
#include "libopus.h"
-#include "mathops.h"
#include "vorbis.h"
#include "audio_frame_queue.h"
int vbr;
int application;
int packet_loss;
+ int fec;
int complexity;
float frame_duration;
int packet_size;
bytestream_put_buffer(&p, "OpusHead", 8);
bytestream_put_byte(&p, 1); /* Version */
bytestream_put_byte(&p, channels);
- bytestream_put_le16(&p, avctx->initial_padding); /* Lookahead samples at 48kHz */
+ bytestream_put_le16(&p, avctx->initial_padding * 48000 / avctx->sample_rate); /* Lookahead samples at 48kHz */
bytestream_put_le32(&p, avctx->sample_rate); /* Original sample rate */
bytestream_put_le16(&p, 0); /* Gain of 0dB is recommended. */
"Unable to set expected packet loss percentage: %s\n",
opus_strerror(ret));
+ ret = opus_multistream_encoder_ctl(enc,
+ OPUS_SET_INBAND_FEC(opts->fec));
+ if (ret != OPUS_OK)
+ av_log(avctx, AV_LOG_WARNING,
+ "Unable to set inband FEC: %s\n",
+ opus_strerror(ret));
+
if (avctx->cutoff) {
ret = opus_multistream_encoder_ctl(enc,
OPUS_SET_MAX_BANDWIDTH(opts->max_bandwidth));
return 0;
}
-static int libopus_check_ambisonics_channels(AVCodecContext *avctx) {
- int channels = avctx->channels;
- int ambisonic_order = ff_sqrt(channels) - 1;
- if (channels != ((ambisonic_order + 1) * (ambisonic_order + 1)) &&
- channels != ((ambisonic_order + 1) * (ambisonic_order + 1) + 2)) {
- av_log(avctx, AV_LOG_ERROR,
- "Ambisonics coding is only specified for channel counts"
- " which can be written as (n + 1)^2 or (n + 1)^2 + 2"
- " for nonnegative integer n\n");
- return AVERROR_INVALIDDATA;
- }
-
- return 0;
-}
-
static int libopus_validate_layout_and_get_channel_map(
AVCodecContext *avctx,
int mapping_family,
channel_map = ff_vorbis_channel_layout_offsets[avctx->channels - 1];
}
break;
- case 2:
- ret = libopus_check_max_channels(avctx, 227);
- if (ret == 0) {
- ret = libopus_check_ambisonics_channels(avctx);
- }
- break;
case 255:
ret = libopus_check_max_channels(avctx, 254);
break;
// Check if subtraction resulted in an overflow
if ((discard_padding < opus->opts.packet_size) != (avpkt->duration > 0)) {
av_packet_unref(avpkt);
- av_free(avpkt);
return AVERROR(EINVAL);
}
if (discard_padding > 0) {
10);
if(!side_data) {
av_packet_unref(avpkt);
- av_free(avpkt);
return AVERROR(ENOMEM);
}
AV_WL32(side_data + 4, discard_padding);
{ "lowdelay", "Restrict to only the lowest delay modes", 0, AV_OPT_TYPE_CONST, { .i64 = OPUS_APPLICATION_RESTRICTED_LOWDELAY }, 0, 0, FLAGS, "application" },
{ "frame_duration", "Duration of a frame in milliseconds", OFFSET(frame_duration), AV_OPT_TYPE_FLOAT, { .dbl = 20.0 }, 2.5, 120.0, FLAGS },
{ "packet_loss", "Expected packet loss percentage", OFFSET(packet_loss), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, FLAGS },
+ { "fec", "Enable inband FEC. Expected packet loss must be non-zero", OFFSET(fec), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
{ "vbr", "Variable bit rate mode", OFFSET(vbr), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 2, FLAGS, "vbr" },
{ "off", "Use constant bit rate", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "vbr" },
{ "on", "Use variable bit rate", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "vbr" },
48000, 24000, 16000, 12000, 8000, 0,
};
-AVCodec ff_libopus_encoder = {
+const AVCodec ff_libopus_encoder = {
.name = "libopus",
.long_name = NULL_IF_CONFIG_SMALL("libopus Opus"),
.type = AVMEDIA_TYPE_AUDIO,