Example Recorder Implementation

Below are the header and cpp files for a Media Recorder Implementation, in order for this recorder to be used by the C++ SDK it must be passed to the conference service as using the dolbyio::comms::services::media_io. Now when a conference is joined all incoming media will be passed to the recorder implementation.

The recorder should be configured appropriately to be used for handling encoded or raw video and PCM/AAC audio. The application should set this configuration before passing the recorder implementation to the conference service.

The interfaces inheritted from by this custom_recorder example must be implemented by any custom recorder which wishes to receive video and audio frames.

At the bottom of the page is a sample CMakeLists.txt which shows how to create a library for this custom recorder, then the library can be linked against the executable shown in the

Sample application section if you want to use a custom recorder module.

custom_recorder.h

/***************************************************************************
 * This program is licensed by the accompanying "license" file. This file is
 * distributed "AS IS" AND WITHOUT WARRANTY OF ANY KIND WHATSOEVER, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 *                Copyright (C) 2022 by Dolby Laboratories.
 ***************************************************************************/

#include <dolbyio/comms/media_engine/media_engine.h>
#include <dolbyio/comms/sdk.h>

#include <memory>
#include <string>

class custom_recorder_impl : private dolbyio::comms::audio_sink,
                             private dolbyio::comms::video_sink,
                             private dolbyio::comms::video_sink_encoded,
                             public dolbyio::comms::media_sink_interface {
 public:
  enum class audio_format { NONE, PCM, AAC };

  enum class video_format { NONE, ENCODED, ENCODED_OPTIMIZED, YUV };

  custom_recorder_impl(dolbyio::comms::sdk& sdk, video_format video, audio_format audio);
  ~custom_recorder_impl() = default;

  dolbyio::comms::video_sink* video_raw();

  // audio_recorder interface
  void handle_audio(const std::string&, const std::string&, const int16_t*, size_t, int, size_t) override;

  // video_recorder_yuv interface
  void handle_frame(const std::string&, const std::string&, std::unique_ptr<dolbyio::comms::video_frame>) override;

  // video_recorder_encoded interface
  dolbyio::comms::video_sink_encoded::decoder_config configure_encoded_sink(const std::string&,
                                                                            const std::string&) override;

  void handle_frame_encoded(const std::string&, std::unique_ptr<dolbyio::comms::encoded_video_frame>) override;

  decoder_config decoder_configuration() const override;

  // media_sink_interface
  dolbyio::comms::audio_sink* audio() override;
  dolbyio::comms::video_sink_encoded* video_enc() override;

 private:
  dolbyio::comms::sdk& sdk_;

  audio_format af_{audio_format::NONE};
  video_format vf_{video_format::NONE};
};

custom_recorder.cc

/***************************************************************************
 * This program is licensed by the accompanying "license" file. This file is
 * distributed "AS IS" AND WITHOUT WARRANTY OF ANY KIND WHATSOEVER, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 *                Copyright (C) 2022 by Dolby Laboratories.
 ***************************************************************************/

#include "custom_recorder.h"

using decoder_config = dolbyio::comms::video_sink_encoded::decoder_config;

custom_recorder_impl::custom_recorder_impl(dolbyio::comms::sdk& sdk, video_format video, audio_format audio)
    : sdk_(sdk), af_(audio), vf_(video) {
  switch (vf_) {
    case custom_recorder_impl::video_format::YUV: {
      wait(sdk_.video().remote().set_video_sink(this));
      break;
    }
    case custom_recorder_impl::video_format::ENCODED:
    case custom_recorder_impl::video_format::ENCODED_OPTIMIZED: {
      wait(sdk_.media_io().set_encoded_video_sink(this));
      break;
    }
    case custom_recorder_impl::video_format::NONE: {
      wait(sdk_.video().remote().set_video_sink(nullptr));
      wait(sdk_.media_io().set_encoded_video_sink(nullptr));
      break;
    }
  }

  if (af_ != custom_recorder_impl::audio_format::NONE) {
    wait(sdk_.media_io().set_audio_sink(this));
  } else {
    wait(sdk_.media_io().set_audio_sink(nullptr));
  }
}

void custom_recorder_impl::handle_audio(const std::string&, const std::string&, const int16_t*, size_t, int, size_t) {
  // handle audio frame
}

void custom_recorder_impl::handle_frame(const std::string&,
                                        const std::string&,
                                        std::unique_ptr<dolbyio::comms::video_frame>) {
  // handle raw video frame
}

dolbyio::comms::video_sink_encoded::decoder_config custom_recorder_impl::configure_encoded_sink(const std::string&,
                                                                                                const std::string&) {
  // set the codec for encoded video frames
  if (vf_ == video_format::ENCODED_OPTIMIZED)
    return decoder_config::optimized_decoding;
  else
    return decoder_config::full_decoding;
}

void custom_recorder_impl::handle_frame_encoded(const std::string&,
                                                std::unique_ptr<dolbyio::comms::encoded_video_frame>) {
  // handle encoded video frame
}

dolbyio::comms::video_sink_encoded::decoder_config custom_recorder_impl::decoder_configuration() const {
  return vf_ == video_format::ENCODED_OPTIMIZED ? decoder_config::optimized_decoding : decoder_config::full_decoding;
}

dolbyio::comms::audio_sink* custom_recorder_impl::audio() {
  if (af_ != audio_format::NONE)
    return this;

  return nullptr;
}

dolbyio::comms::video_sink* custom_recorder_impl::video_raw() {
  if (vf_ == video_format::YUV)
    return this;

  return nullptr;
}

dolbyio::comms::video_sink_encoded* custom_recorder_impl::video_enc() {
  if (vf_ == video_format::ENCODED)
    return this;

  return nullptr;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.0...3.21)

add_library(custom_recorder STATIC
	custom_recorder.h
	custom_recorder.cc
)

target_link_libraries(custom_recorder
	DolbyioComms::sdk
)

# Enable the deprecated wait
add_compile_definitions(DOLBYIO_COMMS_ENABLE_DEPRECATED_WAIT)