// libjingle
// Copyright 2004 Google Inc.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//  1. Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//  3. The name of the author may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "talk/media/base/filemediaengine.h"

#include <limits.h>

#include "talk/media/base/rtpdump.h"
#include "talk/media/base/rtputils.h"
#include "talk/media/base/streamparams.h"
#include "webrtc/base/buffer.h"
#include "webrtc/base/event.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/pathutils.h"
#include "webrtc/base/stream.h"

namespace cricket {

///////////////////////////////////////////////////////////////////////////
// Implementation of FileMediaEngine.
///////////////////////////////////////////////////////////////////////////
int FileMediaEngine::GetCapabilities() {
  int capabilities = 0;
  if (!voice_input_filename_.empty()) {
    capabilities |= AUDIO_SEND;
  }
  if (!voice_output_filename_.empty()) {
    capabilities |= AUDIO_RECV;
  }
  if (!video_input_filename_.empty()) {
    capabilities |= VIDEO_SEND;
  }
  if (!video_output_filename_.empty()) {
    capabilities |= VIDEO_RECV;
  }
  return capabilities;
}

VoiceMediaChannel* FileMediaEngine::CreateChannel() {
  rtc::FileStream* input_file_stream = NULL;
  rtc::FileStream* output_file_stream = NULL;

  if (voice_input_filename_.empty() && voice_output_filename_.empty())
    return NULL;
  if (!voice_input_filename_.empty()) {
    input_file_stream = rtc::Filesystem::OpenFile(
        rtc::Pathname(voice_input_filename_), "rb");
    if (!input_file_stream) {
      LOG(LS_ERROR) << "Not able to open the input audio stream file.";
      return NULL;
    }
  }

  if (!voice_output_filename_.empty()) {
    output_file_stream = rtc::Filesystem::OpenFile(
        rtc::Pathname(voice_output_filename_), "wb");
    if (!output_file_stream) {
      delete input_file_stream;
      LOG(LS_ERROR) << "Not able to open the output audio stream file.";
      return NULL;
    }
  }

  return new FileVoiceChannel(input_file_stream, output_file_stream,
                              rtp_sender_thread_);
}

VideoMediaChannel* FileMediaEngine::CreateVideoChannel(
    const VideoOptions& options,
    VoiceMediaChannel* voice_ch) {
  rtc::FileStream* input_file_stream = NULL;
  rtc::FileStream* output_file_stream = NULL;

  if (video_input_filename_.empty() && video_output_filename_.empty())
      return NULL;

  if (!video_input_filename_.empty()) {
    input_file_stream = rtc::Filesystem::OpenFile(
        rtc::Pathname(video_input_filename_), "rb");
    if (!input_file_stream) {
      LOG(LS_ERROR) << "Not able to open the input video stream file.";
      return NULL;
    }
  }

  if (!video_output_filename_.empty()) {
    output_file_stream = rtc::Filesystem::OpenFile(
        rtc::Pathname(video_output_filename_), "wb");
    if (!output_file_stream) {
      delete input_file_stream;
      LOG(LS_ERROR) << "Not able to open the output video stream file.";
      return NULL;
    }
  }

  FileVideoChannel* channel = new FileVideoChannel(
      input_file_stream, output_file_stream, rtp_sender_thread_);
  channel->SetOptions(options);
  return channel;
}

///////////////////////////////////////////////////////////////////////////
// Definition of RtpSenderReceiver.
///////////////////////////////////////////////////////////////////////////
class RtpSenderReceiver : public rtc::MessageHandler {
 public:
  RtpSenderReceiver(MediaChannel* channel,
                    rtc::StreamInterface* input_file_stream,
                    rtc::StreamInterface* output_file_stream,
                    rtc::Thread* sender_thread);
  virtual ~RtpSenderReceiver();

  // Called by media channel. Context: media channel thread.
  bool SetSend(bool send);
  void SetSendSsrc(uint32 ssrc);
  void OnPacketReceived(rtc::Buffer* packet);

  // Override virtual method of parent MessageHandler. Context: Worker Thread.
  virtual void OnMessage(rtc::Message* pmsg);

 private:
  // Read the next RTP dump packet, whose RTP SSRC is the same as first_ssrc_.
  // Return true if successful.
  bool ReadNextPacket(RtpDumpPacket* packet);
  // Send a RTP packet to the network. The input parameter data points to the
  // start of the RTP packet and len is the packet size. Return true if the sent
  // size is equal to len.
  bool SendRtpPacket(const void* data, size_t len);

  MediaChannel* media_channel_;
  rtc::scoped_ptr<rtc::StreamInterface> input_stream_;
  rtc::scoped_ptr<rtc::StreamInterface> output_stream_;
  rtc::scoped_ptr<RtpDumpLoopReader> rtp_dump_reader_;
  rtc::scoped_ptr<RtpDumpWriter> rtp_dump_writer_;
  rtc::Thread* sender_thread_;
  bool own_sender_thread_;
  // RTP dump packet read from the input stream.
  RtpDumpPacket rtp_dump_packet_;
  uint32 start_send_time_;
  bool sending_;
  bool first_packet_;
  uint32 first_ssrc_;

  DISALLOW_COPY_AND_ASSIGN(RtpSenderReceiver);
};

///////////////////////////////////////////////////////////////////////////
// Implementation of RtpSenderReceiver.
///////////////////////////////////////////////////////////////////////////
RtpSenderReceiver::RtpSenderReceiver(
    MediaChannel* channel,
    rtc::StreamInterface* input_file_stream,
    rtc::StreamInterface* output_file_stream,
    rtc::Thread* sender_thread)
    : media_channel_(channel),
      input_stream_(input_file_stream),
      output_stream_(output_file_stream),
      sending_(false),
      first_packet_(true) {
  if (sender_thread == NULL) {
    sender_thread_ = new rtc::Thread();
    own_sender_thread_ = true;
  } else {
    sender_thread_ = sender_thread;
    own_sender_thread_ = false;
  }

  if (input_stream_) {
    rtp_dump_reader_.reset(new RtpDumpLoopReader(input_stream_.get()));
    // Start the sender thread, which reads rtp dump records, waits based on
    // the record timestamps, and sends the RTP packets to the network.
    if (own_sender_thread_) {
      sender_thread_->Start();
    }
  }

  // Create a rtp dump writer for the output RTP dump stream.
  if (output_stream_) {
    rtp_dump_writer_.reset(new RtpDumpWriter(output_stream_.get()));
  }
}

RtpSenderReceiver::~RtpSenderReceiver() {
  if (own_sender_thread_) {
    sender_thread_->Stop();
    delete sender_thread_;
  }
}

bool RtpSenderReceiver::SetSend(bool send) {
  bool was_sending = sending_;
  sending_ = send;
  if (!was_sending && sending_) {
    sender_thread_->PostDelayed(0, this);  // Wake up the send thread.
    start_send_time_ = rtc::Time();
  }
  return true;
}

void RtpSenderReceiver::SetSendSsrc(uint32 ssrc) {
  if (rtp_dump_reader_) {
    rtp_dump_reader_->SetSsrc(ssrc);
  }
}

void RtpSenderReceiver::OnPacketReceived(rtc::Buffer* packet) {
  if (rtp_dump_writer_) {
    rtp_dump_writer_->WriteRtpPacket(packet->data(), packet->length());
  }
}

void RtpSenderReceiver::OnMessage(rtc::Message* pmsg) {
  if (!sending_) {
    // If the sender thread is not sending, ignore this message. The thread goes
    // to sleep until SetSend(true) wakes it up.
    return;
  }
  if (!first_packet_) {
    // Send the previously read packet.
    SendRtpPacket(&rtp_dump_packet_.data[0], rtp_dump_packet_.data.size());
  }

  if (ReadNextPacket(&rtp_dump_packet_)) {
    int wait = rtc::TimeUntil(
        start_send_time_ + rtp_dump_packet_.elapsed_time);
    wait = rtc::_max(0, wait);
    sender_thread_->PostDelayed(wait, this);
  } else {
    sender_thread_->Quit();
  }
}

bool RtpSenderReceiver::ReadNextPacket(RtpDumpPacket* packet) {
  while (rtc::SR_SUCCESS == rtp_dump_reader_->ReadPacket(packet)) {
    uint32 ssrc;
    if (!packet->GetRtpSsrc(&ssrc)) {
      return false;
    }
    if (first_packet_) {
      first_packet_ = false;
      first_ssrc_ = ssrc;
    }
    if (ssrc == first_ssrc_) {
      return true;
    }
  }
  return false;
}

bool RtpSenderReceiver::SendRtpPacket(const void* data, size_t len) {
  if (!media_channel_)
    return false;

  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
  return media_channel_->SendPacket(&packet);
}

///////////////////////////////////////////////////////////////////////////
// Implementation of FileVoiceChannel.
///////////////////////////////////////////////////////////////////////////
FileVoiceChannel::FileVoiceChannel(
    rtc::StreamInterface* input_file_stream,
    rtc::StreamInterface* output_file_stream,
    rtc::Thread* rtp_sender_thread)
    : send_ssrc_(0),
      rtp_sender_receiver_(new RtpSenderReceiver(this, input_file_stream,
                                                 output_file_stream,
                                                 rtp_sender_thread)) {}

FileVoiceChannel::~FileVoiceChannel() {}

bool FileVoiceChannel::SetSendCodecs(const std::vector<AudioCodec>& codecs) {
  // TODO(whyuan): Check the format of RTP dump input.
  return true;
}

bool FileVoiceChannel::SetSend(SendFlags flag) {
  return rtp_sender_receiver_->SetSend(flag != SEND_NOTHING);
}

bool FileVoiceChannel::AddSendStream(const StreamParams& sp) {
  if (send_ssrc_ != 0 || sp.ssrcs.size() != 1) {
    LOG(LS_ERROR) << "FileVoiceChannel only supports one send stream.";
    return false;
  }
  send_ssrc_ = sp.ssrcs[0];
  rtp_sender_receiver_->SetSendSsrc(send_ssrc_);
  return true;
}

bool FileVoiceChannel::RemoveSendStream(uint32 ssrc) {
  if (ssrc != send_ssrc_)
    return false;
  send_ssrc_ = 0;
  rtp_sender_receiver_->SetSendSsrc(send_ssrc_);
  return true;
}

void FileVoiceChannel::OnPacketReceived(
    rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
  rtp_sender_receiver_->OnPacketReceived(packet);
}

///////////////////////////////////////////////////////////////////////////
// Implementation of FileVideoChannel.
///////////////////////////////////////////////////////////////////////////
FileVideoChannel::FileVideoChannel(
    rtc::StreamInterface* input_file_stream,
    rtc::StreamInterface* output_file_stream,
    rtc::Thread* rtp_sender_thread)
    : send_ssrc_(0),
      rtp_sender_receiver_(new RtpSenderReceiver(this, input_file_stream,
                                                 output_file_stream,
                                                 rtp_sender_thread)) {}

FileVideoChannel::~FileVideoChannel() {}

bool FileVideoChannel::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
  // TODO(whyuan): Check the format of RTP dump input.
  return true;
}

bool FileVideoChannel::SetSend(bool send) {
  return rtp_sender_receiver_->SetSend(send);
}

bool FileVideoChannel::AddSendStream(const StreamParams& sp) {
  if (send_ssrc_ != 0 || sp.ssrcs.size() != 1) {
    LOG(LS_ERROR) << "FileVideoChannel only support one send stream.";
    return false;
  }
  send_ssrc_ = sp.ssrcs[0];
  rtp_sender_receiver_->SetSendSsrc(send_ssrc_);
  return true;
}

bool FileVideoChannel::RemoveSendStream(uint32 ssrc) {
  if (ssrc != send_ssrc_)
    return false;
  send_ssrc_ = 0;
  rtp_sender_receiver_->SetSendSsrc(send_ssrc_);
  return true;
}

void FileVideoChannel::OnPacketReceived(
    rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
  rtp_sender_receiver_->OnPacketReceived(packet);
}

}  // namespace cricket
