chromium/chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder.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_ASSISTANT_AUDIO_DECODER_ASSISTANT_AUDIO_DECODER_H_
#define CHROMEOS_ASH_SERVICES_ASSISTANT_AUDIO_DECODER_ASSISTANT_AUDIO_DECODER_H_

#include <memory>

#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/threading/thread.h"
#include "chromeos/ash/services/assistant/public/mojom/assistant_audio_decoder.mojom.h"
#include "media/filters/blocking_url_protocol.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"

namespace media {
class AudioFileReader;
class AudioBus;
class DataSource;
}  // namespace media

namespace ash::assistant {

class AssistantAudioDecoder : public mojom::AssistantAudioDecoder {
 public:
  AssistantAudioDecoder(
      mojo::PendingRemote<mojom::AssistantAudioDecoderClient> client,
      mojo::PendingRemote<mojom::AssistantMediaDataSource> data_source);

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

  ~AssistantAudioDecoder() override;

  // Called by |client_| on main thread.
  void OpenDecoder(OpenDecoderCallback callback) override;
  void Decode() override;
  void CloseDecoder(CloseDecoderCallback callback) override;

 private:
  // Calls |decoder_| to decode on media thread.
  void OpenDecoderOnMediaThread();
  void DecodeOnMediaThread();
  void CloseDecoderOnMediaThread();

  // Calls |client_| methods on main thread.
  void OnDecoderInitializedOnThread(int sample_rate, int channels);
  void OnBufferDecodedOnThread(
      const std::vector<std::unique_ptr<media::AudioBus>>&
          decoded_audio_buffers);

  // Error callback for media::BlockingUrlProtocol. Only run on media thread.
  void OnDataReadError();

  void OnConnectionError();
  void RunCallbacksAsClosed();

  mojo::Remote<mojom::AssistantAudioDecoderClient> client_;
  scoped_refptr<base::SequencedTaskRunner> task_runner_;

  OpenDecoderCallback open_callback_;
  CloseDecoderCallback close_callback_;
  bool closed_ = false;
  bool read_error_ = false;

  // Weak reference to |this| for use by the media thread. Note, ordering is
  // important here. This _must_ appear before |media_thread_| so that the media
  // thread is destroyed (and joined) first, and hence any attempt to copy
  // |weak_this_| happens before it is destroyed.
  base::WeakPtr<AssistantAudioDecoder> weak_this_;

  std::unique_ptr<media::DataSource> data_source_;
  std::unique_ptr<media::BlockingUrlProtocol> protocol_;
  std::unique_ptr<media::AudioFileReader> decoder_;
  std::unique_ptr<base::Thread> media_thread_;

  base::WeakPtrFactory<AssistantAudioDecoder> weak_factory_;
};

}  // namespace ash::assistant

#endif  // CHROMEOS_ASH_SERVICES_ASSISTANT_AUDIO_DECODER_ASSISTANT_AUDIO_DECODER_H_