chromium/chromecast/media/audio/mixer_service/mixer_socket.h

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMECAST_MEDIA_AUDIO_MIXER_SERVICE_MIXER_SOCKET_H_
#define CHROMECAST_MEDIA_AUDIO_MIXER_SERVICE_MIXER_SOCKET_H_

#include <cstdint>

#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "chromecast/media/audio/net/audio_socket.h"

namespace net {
class StreamSocket;
}  // namespace net

namespace chromecast {
class IOBufferPool;

namespace media {
namespace mixer_service {
class Generic;

class MixerSocket {
 public:
  static constexpr int kAudioMessageHeaderSize =
      AudioSocket::kAudioMessageHeaderSize;

  class Delegate : public AudioSocket::Delegate {
   public:
    // Called when metadata is received from the other side of the connection.
    // Return |true| if the socket should continue to receive messages.
    virtual bool HandleMetadata(const Generic& message);

   protected:
    ~Delegate() override = default;
  };

  virtual ~MixerSocket() = default;

  virtual void SetLocalCounterpart(
      base::WeakPtr<AudioSocket> local_counterpart,
      scoped_refptr<base::SequencedTaskRunner> counterpart_task_runner) = 0;
  virtual base::WeakPtr<AudioSocket> GetAudioSocketWeakPtr() = 0;

  // Sets/changes the delegate. Must be called immediately after creation
  // (ie, synchronously on the same sequence).
  virtual void SetDelegate(Delegate* delegate) = 0;

  // Adds a |buffer_pool| used to allocate buffers to receive messages into,
  // and for sending protos. If the pool-allocated buffers are too small for a
  // given message, a normal IOBuffer will be dynamically allocated instead.
  virtual void UseBufferPool(scoped_refptr<IOBufferPool> buffer_pool) = 0;

  // Prepares |audio_buffer| and then sends it across the connection. Returns
  // |false| if the audio could not be sent.
  virtual bool SendAudioBuffer(scoped_refptr<net::IOBuffer> audio_buffer,
                               int filled_bytes,
                               int64_t timestamp) = 0;

  // Sends an arbitrary protobuf across the connection. |type| indicates the
  // type of message; if the write cannot complete immediately, one message of
  // each type will be stored for later sending; if a newer message is sent with
  // the same type, then the previous message is overwritten. When writes become
  // available again, the stored messages are written in order of |type| (lowest
  // type first). Note that |type| is completely determined by the caller, and
  // you can reuse the same type value for different messages as long as they
  // are on different socket instances. A type of 0 means to never store the
  // message. Returns |false| if the message was not sent or stored.
  virtual bool SendProto(int type,
                         const google::protobuf::MessageLite& message) = 0;

  // Resumes receiving messages. Delegate calls may be called synchronously
  // from within this method.
  virtual void ReceiveMoreMessages() = 0;
};

// AudioSocket implementation for sending and receiving messages to/from the
// mixer service.
class MixerSocketImpl : public MixerSocket {
 public:
  explicit MixerSocketImpl(std::unique_ptr<net::StreamSocket> socket);
  MixerSocketImpl(const MixerSocketImpl&) = delete;
  MixerSocketImpl& operator=(const MixerSocketImpl&) = delete;
  ~MixerSocketImpl() override;

  // Used to create local (in-process) connections.
  MixerSocketImpl();
  void SetLocalCounterpart(base::WeakPtr<AudioSocket> local_counterpart,
                           scoped_refptr<base::SequencedTaskRunner>
                               counterpart_task_runner) override;
  base::WeakPtr<AudioSocket> GetAudioSocketWeakPtr() override;

  void SetDelegate(Delegate* delegate) override;

  void UseBufferPool(scoped_refptr<IOBufferPool> buffer_pool) override;

  bool SendAudioBuffer(scoped_refptr<net::IOBuffer> audio_buffer,
                       int filled_bytes,
                       int64_t timestamp) override;
  bool SendProto(int type,
                 const google::protobuf::MessageLite& message) override;
  void ReceiveMoreMessages() override;

 private:
  class AudioSocketExtension : public AudioSocket {
   public:
    explicit AudioSocketExtension(std::unique_ptr<net::StreamSocket> socket);
    AudioSocketExtension(const MixerSocketImpl&) = delete;
    AudioSocketExtension& operator=(const MixerSocketImpl&) = delete;
    ~AudioSocketExtension() override;

    // Used to create local (in-process) connections.
    AudioSocketExtension();

    void SetDelegate(MixerSocket::Delegate* delegate);

   private:
    bool ParseMetadata(char* data, size_t size) override;

    MixerSocket::Delegate* delegate_ = nullptr;
  };

  std::unique_ptr<AudioSocketExtension> audio_socket_ = nullptr;
};

}  // namespace mixer_service
}  // namespace media
}  // namespace chromecast

#endif  // CHROMECAST_MEDIA_AUDIO_MIXER_SERVICE_MIXER_SOCKET_H_