/*
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef MEDIA_FILTERS_SHELL_AUDIO_RENDERER_IMPL_H_
#define MEDIA_FILTERS_SHELL_AUDIO_RENDERER_IMPL_H_

#include "base/callback.h"
#include "base/message_loop.h"
#include "media/base/audio_decoder.h"
#include "media/filters/shell_audio_renderer.h"

namespace media {

class AudioDecoderSelector;
class DecryptingDemuxerStream;

class MEDIA_EXPORT ShellAudioRendererImpl : public ShellAudioRenderer {
 public:
  explicit ShellAudioRendererImpl(
      AudioRendererSink* sink,
      const SetDecryptorReadyCB& set_decryptor_ready_cb,
      const scoped_refptr<base::MessageLoopProxy>& message_loop);

  // ======== AudioRenderer Implementation

  // Initialize a AudioRenderer with the given AudioDecoder, executing the
  // |init_cb| upon completion.
  //
  // |statistics_cb| is executed periodically with audio rendering stats.
  //
  // |underflow_cb| is executed when the renderer runs out of data to pass to
  // the audio card during playback. ResumeAfterUnderflow() must be called
  // to resume playback. Pause(), Preroll(), or Stop() cancels the underflow
  // condition.
  //
  // |time_cb| is executed whenever time has advanced by way of audio rendering.
  //
  // |ended_cb| is executed when audio rendering has reached the end of stream.
  //
  // |disabled_cb| is executed when audio rendering has been disabled due to
  // external factors (i.e., device was removed). |time_cb| will no longer be
  // executed.
  //
  // |error_cb| is executed if an error was encountered.
  virtual void Initialize(const scoped_refptr<DemuxerStream>& stream,
                          const AudioDecoderList& decoders,
                          const PipelineStatusCB& init_cb,
                          const StatisticsCB& statistics_cb,
                          const base::Closure& underflow_cb,
                          const TimeCB& time_cb,
                          const base::Closure& ended_cb,
                          const base::Closure& disabled_cb,
                          const PipelineStatusCB& error_cb) OVERRIDE;

  // Start prerolling audio data for samples starting at |time|, executing
  // |callback| when completed.
  //
  // Only valid to call after a successful Initialize() or Flush().
  virtual void Preroll(base::TimeDelta time,
                       const PipelineStatusCB& callback) OVERRIDE;

  // Sets the output volume.
  virtual void SetVolume(float volume) OVERRIDE;

  // Resumes playback after underflow occurs.
  //
  // |buffer_more_audio| is set to true if you want to increase the size of the
  // decoded audio buffer.
  virtual void ResumeAfterUnderflow(bool buffer_more_audio) OVERRIDE;

  // The pipeline has resumed playback.  Filters can continue requesting reads.
  // Filters may implement this method if they need to respond to this call.
  virtual void Play(const base::Closure& callback) OVERRIDE;

  // The pipeline has paused playback.  Filters should stop buffer exchange.
  // Filters may implement this method if they need to respond to this call.
  virtual void Pause(const base::Closure& callback) OVERRIDE;

  // The pipeline has been flushed.  Filters should return buffer to owners.
  // Filters may implement this method if they need to respond to this call.
  virtual void Flush(const base::Closure& callback) OVERRIDE;

  // The pipeline is being stopped either as a result of an error or because
  // the client called Stop().
  virtual void Stop(const base::Closure& callback) OVERRIDE;

  // The pipeline playback rate has been changed.  Filters may implement this
  // method if they need to respond to this call.
  virtual void SetPlaybackRate(float playback_rate) OVERRIDE;

  // Carry out any actions required to seek to the given time, executing the
  // callback upon completion.
  // virtual void Seek(base::TimeDelta time,
  //                   const PipelineStatusCB& callback) OVERRIDE;

 protected:
  virtual ~ShellAudioRendererImpl();

  void DoPlay();
  void DoPreroll(base::TimeDelta time, const PipelineStatusCB& callback);
  void DoUnderflow();
  void DoResumeAfterUnderflow(bool buffer_more_audio);
  void DoSinkFull();

  // AudioRendererSink::RenderCallback implementation.
  // Attempts to completely fill all channels of |dest|, returns actual
  // number of frames filled.
  // Render() is run on the system audio thread
  virtual int Render(AudioBus* dest, int audio_delay_milliseconds) OVERRIDE;
  virtual void OnRenderError() OVERRIDE;
  virtual void SinkFull() OVERRIDE;
  virtual void SinkUnderflow() OVERRIDE;

  void DecodedAudioReady(AudioDecoder::Status status,
                         const AudioDecoder::Buffers& buffers);

  void OnDecoderSelected(
      scoped_ptr<AudioDecoderSelector> decoder_selector,
      const scoped_refptr<AudioDecoder>& selected_decoder,
      const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream);

  void OnDecoderReset(const base::Closure& callback);

  enum State {
    kUninitialized,
    kPaused,
    kPrerolling,
    kPlaying,
    kUnderflow,
    kRebuffering,
    kStopping,
    kStopped,
  };

  bool ShouldQueueRead(State state);

  // objects communicating with the rest of the filter graph
  scoped_refptr<AudioRendererSink> sink_;
  SetDecryptorReadyCB set_decryptor_ready_cb_;
  scoped_refptr<base::MessageLoopProxy> message_loop_;
  scoped_refptr<AudioDecoder> decoder_;
  base::Closure underflow_cb_;
  TimeCB time_cb_;
  base::Closure ended_cb_;
  PipelineStatusCB preroll_cb_;
  base::TimeDelta preroll_timestamp_;
  PipelineStatusCB init_cb_;
  PipelineStatusCB error_cb_;

  State state_;

  enum EOSState {
    kWaitingForEOS,
    kReceivedEOS,
    kRenderedEOS,
    kPlayedEOS,
  };
  EOSState end_of_stream_state_;
  float playback_rate_;
  AudioParameters audio_parameters_;

  AudioBus* decoded_audio_bus_;
  AudioDecoder::Status decode_status_;
  bool decode_complete_;

  // Callback that is called from the H/W renderer thread when it is finished
  // requesting audio samples
  base::Lock renderer_cb_lock_;
  base::Closure renderer_idle_cb_;

  // modified only by MediaPipeline thread while decode_complete is false
  // Can be read by any thread when it is true
  base::TimeDelta buffered_timestamp_;
  // Read/written only in Render callback
  base::TimeDelta rendered_timestamp_;
  // Read/written only in Render callback. Indicates how much silence has been
  // written to the sink after EOS was encountered
  base::TimeDelta silence_rendered_;

  // Store the DecryptingDemuxerStream so we can reset it when Stop is
  // requested. As the top level demuxer has no knowledge of the decrypting
  // demuxer stream, the pipeline will not be able to reset the streams during
  // stopping. So we have to reset it.
  scoped_refptr<DecryptingDemuxerStream> decrypting_demuxer_stream_;
};

}  // namespace media

#endif  // MEDIA_FILTERS_SHELL_AUDIO_RENDERER_IMPL_H_
