/*
 *  Copyright (c) 2012 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.
 */

#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_STRATEGY_H_
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_STRATEGY_H_

#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/typedefs.h"

namespace webrtc {

class TelephoneEventHandler;

// This strategy deals with media-specific RTP packet processing.
// This class is not thread-safe and must be protected by its caller.
class RTPReceiverStrategy {
 public:
  static RTPReceiverStrategy* CreateVideoStrategy(int32_t id,
                                                  RtpData* data_callback);
  static RTPReceiverStrategy* CreateAudioStrategy(
      int32_t id, RtpData* data_callback,
      RtpAudioFeedback* incoming_messages_callback);

  virtual ~RTPReceiverStrategy() {}

  // Parses the RTP packet and calls the data callback with the payload data.
  // Implementations are encouraged to use the provided packet buffer and RTP
  // header as arguments to the callback; implementations are also allowed to
  // make changes in the data as necessary. The specific_payload argument
  // provides audio or video-specific data. The is_first_packet argument is true
  // if this packet is either the first packet ever or the first in its frame.
  virtual int32_t ParseRtpPacket(WebRtcRTPHeader* rtp_header,
                                 const PayloadUnion& specific_payload,
                                 bool is_red,
                                 const uint8_t* payload,
                                 uint16_t payload_length,
                                 int64_t timestamp_ms,
                                 bool is_first_packet) = 0;

  virtual TelephoneEventHandler* GetTelephoneEventHandler() = 0;

  // Retrieves the last known applicable frequency.
  virtual int GetPayloadTypeFrequency() const = 0;

  // Computes the current dead-or-alive state.
  virtual RTPAliveType ProcessDeadOrAlive(
      uint16_t last_payload_length) const = 0;

  // Returns true if we should report CSRC changes for this payload type.
  // TODO(phoglund): should move out of here along with other payload stuff.
  virtual bool ShouldReportCsrcChanges(uint8_t payload_type) const = 0;

  // Notifies the strategy that we have created a new non-RED payload type in
  // the payload registry.
  virtual int32_t OnNewPayloadTypeCreated(
      const char payloadName[RTP_PAYLOAD_NAME_SIZE],
      int8_t payloadType,
      uint32_t frequency) = 0;

  // Invokes the OnInitializeDecoder callback in a media-specific way.
  virtual int32_t InvokeOnInitializeDecoder(
      RtpFeedback* callback,
      int32_t id,
      int8_t payload_type,
      const char payload_name[RTP_PAYLOAD_NAME_SIZE],
      const PayloadUnion& specific_payload) const = 0;

  // Checks if the payload type has changed, and returns whether we should
  // reset statistics and/or discard this packet.
  virtual void CheckPayloadChanged(int8_t payload_type,
                                   PayloadUnion* specific_payload,
                                   bool* should_reset_statistics,
                                   bool* should_discard_changes);

  virtual int Energy(uint8_t array_of_energy[kRtpCsrcSize]) const;

  // Stores / retrieves the last media specific payload for later reference.
  void GetLastMediaSpecificPayload(PayloadUnion* payload) const;
  void SetLastMediaSpecificPayload(const PayloadUnion& payload);

 protected:
  // The data callback is where we should send received payload data.
  // See ParseRtpPacket. This class does not claim ownership of the callback.
  // Implementations must NOT hold any critical sections while calling the
  // callback.
  //
  // Note: Implementations may call the callback for other reasons than calls
  // to ParseRtpPacket, for instance if the implementation somehow recovers a
  // packet.
  RTPReceiverStrategy(RtpData* data_callback);

  scoped_ptr<CriticalSectionWrapper> crit_sect_;
  PayloadUnion last_payload_;
  RtpData* data_callback_;
};
}  // namespace webrtc

#endif  // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_STRATEGY_H_
