chromium/chromeos/ash/services/libassistant/audio/audio_stream_handler.h

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

#ifndef CHROMEOS_ASH_SERVICES_LIBASSISTANT_AUDIO_AUDIO_STREAM_HANDLER_H_
#define CHROMEOS_ASH_SERVICES_LIBASSISTANT_AUDIO_AUDIO_STREAM_HANDLER_H_

#include "base/memory/raw_ptr.h"
#include "base/synchronization/lock.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "chromeos/ash/services/assistant/public/mojom/assistant_audio_decoder.mojom.h"
#include "chromeos/assistant/internal/libassistant/shared_headers.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"

namespace ash::libassistant {

class AudioMediaDataSource;

class AudioStreamHandler : public assistant::mojom::AssistantAudioDecoderClient,
                           public assistant_client::AudioOutput::Delegate {
 public:
  using InitCB =
      base::OnceCallback<void(const assistant_client::OutputStreamFormat&)>;

  AudioStreamHandler();

  AudioStreamHandler(const AudioStreamHandler&) = delete;
  AudioStreamHandler& operator=(const AudioStreamHandler&) = delete;

  ~AudioStreamHandler() override;

  void StartAudioDecoder(
      assistant::mojom::AssistantAudioDecoderFactory* audio_decoder_factory,
      assistant_client::AudioOutput::Delegate* delegate,
      InitCB start_device_owner_on_main_thread);

  // assistant::mojom::AssistantAudioDecoderClient overrides:
  void OnNewBuffers(const std::vector<std::vector<uint8_t>>& buffers) override;

  // assistant_client::AudioOutput::Delegate overrides:
  void FillBuffer(void* buffer,
                  int buffer_size,
                  int64_t playback_timestamp,
                  assistant_client::Callback1<int> on_decoded) override;
  void OnEndOfStream() override;
  void OnError(assistant_client::AudioOutput::Error error) override;
  void OnStopped() override;

 private:
  void OnDecoderInitialized(bool success,
                            uint32_t bytes_per_sample,
                            uint32_t samples_per_second,
                            uint32_t channels);
  void StopDelegate();

  void FillBufferOnMainThread(void* buffer,
                              int buffer_size,
                              assistant_client::Callback1<int> on_filled);

  // Called by |FillBufferOnMainThread()| to fill available data. If no
  // available data, it will call |Decode()| to get more data.
  void FillDecodedBuffer(void* buffer, int buffer_size);

  void OnFillBuffer(assistant_client::Callback1<int> on_decoded, int num_bytes);

  void Decode();

  scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
  raw_ptr<assistant_client::AudioOutput::Delegate> delegate_;

  mojo::Receiver<AssistantAudioDecoderClient> client_receiver_{this};
  std::unique_ptr<AudioMediaDataSource> media_data_source_;
  mojo::Remote<assistant::mojom::AssistantAudioDecoder> audio_decoder_;

  // True when there is more decoded data.
  bool no_more_data_ = false;
  // True if |Decode()| called and not all decoded buffers are received, e.g.
  // |buffers_to_receive_| != 0.
  bool is_decoding_ = false;
  // True after |OnStopped()| called.
  bool stopped_ = false;

  // Temporary storage of |buffer| passed by |FillBuffer|.
  raw_ptr<void> buffer_to_copy_ = nullptr;
  // Temporary storage of |buffer_size| passed by |FillBuffer|.
  int size_to_copy_ = 0;
  // Temporary storage of |on_filled| passed by |FillBuffer|.
  assistant_client::Callback1<int> on_filled_;

  InitCB start_device_owner_on_main_thread_;

  base::circular_deque<std::vector<uint8_t>> decoded_data_;

  // The callbacks from Libassistant are called on a different sequence,
  // so this sequence checker ensures that no other methods are called on the
  // libassistant sequence.
  SEQUENCE_CHECKER(sequence_checker_);

  base::WeakPtrFactory<AudioStreamHandler> weak_factory_;
};

}  // namespace ash::libassistant

#endif  // CHROMEOS_ASH_SERVICES_LIBASSISTANT_AUDIO_AUDIO_STREAM_HANDLER_H_