15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/client/audio_decode_scheduler.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/single_thread_task_runner.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/client/audio_player.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/audio_decoder.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/proto/audio.pb.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioDecodeScheduler::Core : public base::RefCountedThreadSafe<Core> {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner,
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       scoped_ptr<AudioPlayer> audio_player);
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Initialize(const protocol::SessionConfig& config);
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ProcessAudioPacket(scoped_ptr<AudioPacket> packet,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const base::Closure& done);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called by AudioDecodeScheduler when it is destroyed.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Detach();
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<Core>;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~Core();
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the audio decoder thread.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DecodePacket(scoped_ptr<AudioPacket> packet, const base::Closure& done);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the main thread.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ProcessDecodedPacket(scoped_ptr<AudioPacket> packet,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const base::Closure& done);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner_;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioDecoder> decoder_;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioPlayer> audio_player_;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Core);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioDecodeScheduler::Core::Core(
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<AudioPlayer> audio_player)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : main_task_runner_(main_task_runner),
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      audio_decode_task_runner_(audio_decode_task_runner),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      audio_player_(audio_player.Pass()) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioDecodeScheduler::Core::~Core() {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioDecodeScheduler::Core::Initialize(
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const protocol::SessionConfig& config) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(main_task_runner_->BelongsToCurrentThread());
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decoder_.reset(AudioDecoder::CreateAudioDecoder(config).release());
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioDecodeScheduler::Core::ProcessAudioPacket(
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<AudioPacket> packet,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& done) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(main_task_runner_->BelongsToCurrentThread());
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_decode_task_runner_->PostTask(FROM_HERE, base::Bind(
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &AudioDecodeScheduler::Core::DecodePacket, this,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Passed(&packet), done));
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioDecodeScheduler::Core::Detach() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(main_task_runner_->BelongsToCurrentThread());
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_player_.reset();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioDecodeScheduler::Core::DecodePacket(
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<AudioPacket> packet,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& done) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(audio_decode_task_runner_->BelongsToCurrentThread());
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioPacket> decoded_packet = decoder_->Decode(packet.Pass());
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_task_runner_->PostTask(FROM_HERE, base::Bind(
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &AudioDecodeScheduler::Core::ProcessDecodedPacket, this,
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Passed(&decoded_packet), done));
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioDecodeScheduler::Core::ProcessDecodedPacket(
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<AudioPacket> packet,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& done) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(main_task_runner_->BelongsToCurrentThread());
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only process |packet| if it is non-NULL.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (packet.get() && audio_player_.get())
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    audio_player_->ProcessAudioPacket(packet.Pass());
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  done.Run();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioDecodeScheduler::AudioDecodeScheduler(
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> audio_decode_task_runner,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<AudioPlayer> audio_player)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : core_(new Core(main_task_runner, audio_decode_task_runner,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     audio_player.Pass())) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioDecodeScheduler::~AudioDecodeScheduler() {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->Detach();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioDecodeScheduler::Initialize(const protocol::SessionConfig& config) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->Initialize(config);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioDecodeScheduler::ProcessAudioPacket(scoped_ptr<AudioPacket> packet,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              const base::Closure& done) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->ProcessAudioPacket(packet.Pass(), done);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
124