From f381f0dfcfed7bf424f59a71f15e2d1a24315d8a Mon Sep 17 00:00:00 2001
From: Adrien Beraud <adrien.beraud@savoirfairelinux.com>
Date: Tue, 10 Oct 2023 14:16:52 -0400
Subject: [PATCH] media decoder: support floating point

Change-Id: Ifea0a1ebd9cc36214b0532c01119333cd269f1a0
---
 src/media/libav_utils.cpp   | 28 ++++++++++++++++++++++++++++
 src/media/libav_utils.h     |  6 ++++++
 src/media/media_decoder.cpp | 16 ++++++++++------
 3 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/src/media/libav_utils.cpp b/src/media/libav_utils.cpp
index 60cee22898..ea22450986 100644
--- a/src/media/libav_utils.cpp
+++ b/src/media/libav_utils.cpp
@@ -56,6 +56,34 @@ av_frame_new_side_data_from_buf(AVFrame* frame, enum AVFrameSideDataType type, A
 namespace jami {
 namespace libav_utils {
 
+AVSampleFormat
+choose_sample_fmt(const AVCodec *codec, const AVSampleFormat *preferred_formats, int preferred_formats_count) {
+    for (int i = 0; i < preferred_formats_count; ++i) {
+        for (auto it = codec->sample_fmts; *it != -1; ++it) {
+            if (*it == preferred_formats[i])
+                return preferred_formats[i];
+        }
+    }
+    return AV_SAMPLE_FMT_NONE;
+}
+
+AVSampleFormat
+choose_sample_fmt_default(const AVCodec* codec, AVSampleFormat defaultFormat) {
+    // List of supported formats, current default first
+    const AVSampleFormat preferred_formats[] = {
+        defaultFormat,
+        AV_SAMPLE_FMT_FLTP,
+        AV_SAMPLE_FMT_FLT,
+        AV_SAMPLE_FMT_S16P,
+        AV_SAMPLE_FMT_S16,
+        AV_SAMPLE_FMT_DBLP,
+        AV_SAMPLE_FMT_DBL,
+        AV_SAMPLE_FMT_S32P,
+        AV_SAMPLE_FMT_S32
+    };
+    return choose_sample_fmt(codec, preferred_formats, sizeof(preferred_formats) / sizeof(preferred_formats[0]));
+}
+
 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
 // protect libav/ffmpeg access
 static int
diff --git a/src/media/libav_utils.h b/src/media/libav_utils.h
index 96e96be1af..2439dd6a2c 100644
--- a/src/media/libav_utils.h
+++ b/src/media/libav_utils.h
@@ -21,6 +21,8 @@
 
 #pragma once
 
+#include <libavutil/samplefmt.h>
+
 #include <vector>
 #include <map>
 #include <string>
@@ -31,6 +33,7 @@ struct AVDictionary;
 struct AVFrame;
 struct AVPixFmtDescriptor;
 struct AVBufferRef;
+struct AVCodec;
 void av_buffer_unref(AVBufferRef **buf);
 }
 
@@ -42,6 +45,9 @@ void av_init();
 const char* const DEFAULT_H264_PROFILE_LEVEL_ID = "profile-level-id=428029";
 const char* const MAX_H264_PROFILE_LEVEL_ID = "profile-level-id=640034";
 
+enum AVSampleFormat choose_sample_fmt(const AVCodec* codec, const enum AVSampleFormat* preferred_formats, int preferred_formats_count);
+enum AVSampleFormat choose_sample_fmt_default(const AVCodec* codec, enum AVSampleFormat defaultFormat);
+
 bool is_yuv_planar(const AVPixFmtDescriptor& desc);
 
 std::string getError(int err);
diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp
index e994f6ca33..a652f97f74 100644
--- a/src/media/media_decoder.cpp
+++ b/src/media/media_decoder.cpp
@@ -27,6 +27,7 @@
 #include "media_io_handle.h"
 #include "audio/ringbuffer.h"
 #include "audio/resampler.h"
+#include "audio/ringbufferpool.h"
 #include "decoder_finder.h"
 #include "manager.h"
 
@@ -147,10 +148,10 @@ MediaDemuxer::openInput(const DeviceParams& params)
     std::string input = params.input;
 #endif
 
-    JAMI_DBG("Trying to open device %s with format %s, pixel format %s, size %dx%d, rate %lf",
-             input.c_str(),
-             params.format.c_str(),
-             params.pixel_format.c_str(),
+    JAMI_LOG("Trying to open input {} with format {}, pixel format {}, size {}x{}, rate {}",
+             input,
+             params.format,
+             params.pixel_format,
              params.width,
              params.height,
              params.framerate.real());
@@ -574,13 +575,13 @@ MediaDecoder::prepareDecoderContext()
 {
     inputDecoder_ = findDecoder(avStream_->codecpar->codec_id);
     if (!inputDecoder_) {
-        JAMI_ERR() << "Unsupported codec";
+        JAMI_ERROR("Unsupported codec");
         return -1;
     }
 
     decoderCtx_ = avcodec_alloc_context3(inputDecoder_);
     if (!decoderCtx_) {
-        JAMI_ERR() << "Failed to create decoder context";
+        JAMI_ERROR("Failed to create decoder context");
         return -1;
     }
     avcodec_parameters_to_context(decoderCtx_, avStream_->codecpar);
@@ -597,6 +598,9 @@ MediaDecoder::prepareDecoderContext()
         if (decoderCtx_->codec_id == AV_CODEC_ID_OPUS) {
             av_opt_set_int(decoderCtx_, "decode_fec", fecEnabled_ ? 1 : 0, AV_OPT_SEARCH_CHILDREN);
         }
+        auto format = libav_utils::choose_sample_fmt_default(inputDecoder_, Manager::instance().getRingBufferPool().getInternalAudioFormat().sampleFormat);
+        decoderCtx_->sample_fmt = format;
+        decoderCtx_->request_sample_fmt = format;
     }
     return 0;
 }
-- 
GitLab