/*
 * 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 <algorithm>
#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->size());
  }
}

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 = std::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
