/*
 * 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_VIDEO_DECODER_IMPL_H_
#define MEDIA_FILTERS_SHELL_VIDEO_DECODER_IMPL_H_

#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/threading/thread.h"
#include "media/base/demuxer_stream.h"
#include "media/base/shell_buffer_factory.h"
#include "media/base/video_decoder.h"
#include "media/base/video_decoder_config.h"

namespace media {

class ShellRawVideoDecoder {
 public:
  enum DecodeStatus {
    FRAME_DECODED,           // Successfully decoded a frame.
    NEED_MORE_DATA,          // Need more data to decode the next frame.
    RETRY_WITH_SAME_BUFFER,  // Retry later with the same input. Note that in
                             // this case the decoder may still return a valid
                             // buffered frame.
    FATAL_ERROR              // Decoder encounters fatal error, abort playback.
  };
  typedef media::DecoderBuffer DecoderBuffer;
  typedef media::VideoDecoderConfig VideoDecoderConfig;
  typedef media::VideoFrame VideoFrame;
  typedef base::Callback<void(DecodeStatus, const scoped_refptr<VideoFrame>&)>
      DecodeCB;

  ShellRawVideoDecoder() {}
  virtual ~ShellRawVideoDecoder() {}
  virtual void Decode(const scoped_refptr<DecoderBuffer>& buffer,
                      const DecodeCB& decode_cb) = 0;
  virtual bool Flush() = 0;
  virtual bool UpdateConfig(const VideoDecoderConfig& config) = 0;
  // See ShellVideoDecoder for more details about the following two functions.
  virtual void NearlyUnderflow() {}
  virtual void HaveEnoughFrames() {}

 private:
  DISALLOW_COPY_AND_ASSIGN(ShellRawVideoDecoder);
};

class ShellRawVideoDecoderFactory {
 public:
  virtual ~ShellRawVideoDecoderFactory() {}

  virtual scoped_ptr<ShellRawVideoDecoder> Create(
      const VideoDecoderConfig& config,
      Decryptor* decryptor,
      bool was_encrypted) = 0;
};

class MEDIA_EXPORT ShellVideoDecoderImpl : public VideoDecoder {
 public:
  ShellVideoDecoderImpl(
      const scoped_refptr<base::MessageLoopProxy>& message_loop,
      ShellRawVideoDecoderFactory* raw_video_decoder_factory);
  ~ShellVideoDecoderImpl() OVERRIDE;

  // ShellVideoDecoder implementation.
  void Initialize(const scoped_refptr<DemuxerStream>& stream,
                  const PipelineStatusCB& status_cb,
                  const StatisticsCB& statistics_cb) OVERRIDE;
  void Read(const ReadCB& read_cb) OVERRIDE;
  void Reset(const base::Closure& closure) OVERRIDE;
  void Stop(const base::Closure& closure) OVERRIDE;
  void NearlyUnderflow() OVERRIDE;
  void HaveEnoughFrames() OVERRIDE;

 private:
  enum DecoderState {
    kUninitialized,
    kNormal,
    kFlushCodec,
    kDecodeFinished,
    kShellDecodeError
  };

  void BufferReady(DemuxerStream::Status status,
                   const scoped_refptr<DecoderBuffer>& buffer);

  // actually makes the call to the platform decoder to decode
  void DecodeBuffer(const scoped_refptr<DecoderBuffer>& buffer);
  // the callback from the raw decoder indicates an operation has been finished.
  void DecodeCallback(ShellRawVideoDecoder::DecodeStatus status,
                      const scoped_refptr<VideoFrame>& frame);
  // Posts a task to read from the demuxer stream.
  void ReadFromDemuxerStream();
  // Reset decoder and call |reset_cb_|.
  void DoReset();
  // called on decoder thread, fatal error on decode, we shut down decode
  void DecoderFatalError();

  DecoderState state_;
  scoped_refptr<base::MessageLoopProxy> media_pipeline_message_loop_;
  ShellRawVideoDecoderFactory* raw_video_decoder_factory_;
  scoped_refptr<DemuxerStream> demuxer_stream_;
  ReadCB read_cb_;
  base::Closure reset_cb_;

  scoped_ptr<ShellRawVideoDecoder> raw_decoder_;

  // TODO: ensure the demuxer can handle multiple EOS requests then remove this
  // hack.
  scoped_refptr<DecoderBuffer> eof_buffer_;

  scoped_refptr<DecoderBuffer> buffer_to_decode_;

  // All decoding tasks will be performed on this thread's message loop
  base::Thread decoder_thread_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(ShellVideoDecoderImpl);
};

}  // namespace media

#endif  // MEDIA_FILTERS_SHELL_VIDEO_DECODER_IMPL_H_
