/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h"

#include <assert.h>
#include <string.h>
#include <iostream>
#include <limits>

#include "webrtc/base/checks.h"
#include "webrtc/call/rtc_event_log.h"
#include "webrtc/modules/audio_coding/neteq/tools/packet.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"

// Files generated at build-time by the protobuf compiler.
#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
#include "external/webrtc/webrtc/call/rtc_event_log.pb.h"
#else
#include "webrtc/call/rtc_event_log.pb.h"
#endif

namespace webrtc {
namespace test {

namespace {

const rtclog::RtpPacket* GetRtpPacket(const rtclog::Event& event) {
  if (!event.has_type() || event.type() != rtclog::Event::RTP_EVENT)
    return nullptr;
  if (!event.has_timestamp_us() || !event.has_rtp_packet())
    return nullptr;
  const rtclog::RtpPacket& rtp_packet = event.rtp_packet();
  if (!rtp_packet.has_type() || rtp_packet.type() != rtclog::AUDIO ||
      !rtp_packet.has_incoming() || !rtp_packet.incoming() ||
      !rtp_packet.has_packet_length() || rtp_packet.packet_length() == 0 ||
      !rtp_packet.has_header() || rtp_packet.header().size() == 0 ||
      rtp_packet.packet_length() < rtp_packet.header().size())
    return nullptr;
  return &rtp_packet;
}

const rtclog::AudioPlayoutEvent* GetAudioPlayoutEvent(
    const rtclog::Event& event) {
  if (!event.has_type() || event.type() != rtclog::Event::AUDIO_PLAYOUT_EVENT)
    return nullptr;
  if (!event.has_timestamp_us() || !event.has_audio_playout_event())
    return nullptr;
  const rtclog::AudioPlayoutEvent& playout_event = event.audio_playout_event();
  if (!playout_event.has_local_ssrc())
    return nullptr;
  return &playout_event;
}

}  // namespace

RtcEventLogSource* RtcEventLogSource::Create(const std::string& file_name) {
  RtcEventLogSource* source = new RtcEventLogSource();
  RTC_CHECK(source->OpenFile(file_name));
  return source;
}

RtcEventLogSource::~RtcEventLogSource() {}

bool RtcEventLogSource::RegisterRtpHeaderExtension(RTPExtensionType type,
                                                   uint8_t id) {
  RTC_CHECK(parser_.get());
  return parser_->RegisterRtpHeaderExtension(type, id);
}

Packet* RtcEventLogSource::NextPacket() {
  while (rtp_packet_index_ < event_log_->stream_size()) {
    const rtclog::Event& event = event_log_->stream(rtp_packet_index_);
    const rtclog::RtpPacket* rtp_packet = GetRtpPacket(event);
    rtp_packet_index_++;
    if (rtp_packet) {
      uint8_t* packet_header = new uint8_t[rtp_packet->header().size()];
      memcpy(packet_header, rtp_packet->header().data(),
             rtp_packet->header().size());
      Packet* packet = new Packet(packet_header, rtp_packet->header().size(),
                                  rtp_packet->packet_length(),
                                  event.timestamp_us() / 1000, *parser_.get());
      if (packet->valid_header()) {
        // Check if the packet should not be filtered out.
        if (!filter_.test(packet->header().payloadType) &&
            !(use_ssrc_filter_ && packet->header().ssrc != ssrc_))
          return packet;
      } else {
        std::cout << "Warning: Packet with index " << (rtp_packet_index_ - 1)
                  << " has an invalid header and will be ignored." << std::endl;
      }
      // The packet has either an invalid header or needs to be filtered out, so
      // it can be deleted.
      delete packet;
    }
  }
  return nullptr;
}

int64_t RtcEventLogSource::NextAudioOutputEventMs() {
  while (audio_output_index_ < event_log_->stream_size()) {
    const rtclog::Event& event = event_log_->stream(audio_output_index_);
    const rtclog::AudioPlayoutEvent* playout_event =
        GetAudioPlayoutEvent(event);
    audio_output_index_++;
    if (playout_event)
      return event.timestamp_us() / 1000;
  }
  return std::numeric_limits<int64_t>::max();
}

RtcEventLogSource::RtcEventLogSource()
    : PacketSource(), parser_(RtpHeaderParser::Create()) {}

bool RtcEventLogSource::OpenFile(const std::string& file_name) {
  event_log_.reset(new rtclog::EventStream());
  return RtcEventLog::ParseRtcEventLog(file_name, event_log_.get());
}

}  // namespace test
}  // namespace webrtc
