/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (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.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is MPEG4IP. * * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved. * * Contributor(s): * Bill May wmay@cisco.com */ /* * player_rtp_bytestream.h - provides an RTP bytestream for the codecs * to access */ #ifndef __RTP_BYTESTREAM_H__ #define __RTP_BYTESTREAM_H__ 1 #include "our_bytestream.h" #include "player_util.h" #include "rtp/rtp.h" #include #include #include class CRtpByteStreamBase : public COurInByteStream { public: CRtpByteStreamBase(const char *name, format_list_t *fmt, unsigned int rtp_pt, int ondemand, uint64_t tickpersec, rtp_packet **head, rtp_packet **tail, int rtp_seq_set, uint16_t rtp_base_seq, int rtp_ts_set, uint32_t rtp_base_ts, int rtcp_received, uint32_t ntp_frac, uint32_t ntp_sec, uint32_t rtp_ts); ~CRtpByteStreamBase(); int eof (void) { return m_eof; }; virtual void reset(void) { player_debug_message("rtp bytestream reset"); init(); m_buffering = 0; m_base_ts_set = 0; m_rtp_base_seq_set = 0; }; void set_skip_on_advance (uint32_t bytes_to_skip) { m_skip_on_advance_bytes = bytes_to_skip; }; double get_max_playtime (void) { if (m_fmt->media->media_range.have_range) { return m_fmt->media->media_range.range_end; } else if (m_fmt->media->parent->session_range.have_range) { return m_fmt->media->parent->session_range.range_end; } return 0.0; }; // various routines for RTP interface. void set_rtp_base_ts(uint32_t t, uint64_t value = 0) { m_base_ts_set = true; m_base_rtp_ts = t; m_base_ts = value; }; void set_rtp_base_seq(uint16_t s) { m_rtp_base_seq_set = true; m_rtp_base_seq = s; }; int can_skip_frame (void) { return 1; } ; void set_wallclock_offset (uint64_t wclock, uint32_t rtp_ts); int rtp_ready (void) { return true; }; void recv_callback(struct rtp *session, rtp_event *e); virtual void flush_rtp_packets(void); int recv_task(int waiting); uint32_t get_last_rtp_timestamp (void) {return m_rtptime_last; }; void remove_packet_rtp_queue(rtp_packet *pak, int free); void pause(void); void set_sync(CPlayerSession *psptr); void syncronize(rtcp_sync_t *sync); protected: bool check_seq (uint16_t seq); void set_last_seq(uint16_t seq); void init(void); // Make sure all classes call this to calculate real time. uint64_t rtp_ts_to_msec(uint32_t rtp_ts, uint64_t uts, uint64_t &wrap_offset); rtp_packet *m_head, *m_tail; int m_offset_in_pak; uint32_t m_skip_on_advance_bytes; uint32_t m_ts; uint64_t m_total; bool m_base_ts_set; uint32_t m_base_rtp_ts; uint64_t m_base_ts; bool m_rtp_base_seq_set; uint16_t m_rtp_base_seq; uint64_t m_timescale; int m_stream_ondemand; uint64_t m_wrap_offset; bool m_rtcp_received; uint64_t m_rtcp_ts; uint32_t m_rtcp_rtp_ts; uint64_t m_wallclock_offset_wrap; void calculate_wallclock_offset_from_rtcp(uint32_t ntp_frac, uint32_t ntp_sec, uint32_t rtp_ts); SDL_mutex *m_rtp_packet_mutex; int m_buffering; uint64_t m_rtp_buffer_time; unsigned int m_rtp_pt; virtual int check_rtp_frame_complete_for_payload_type(void); virtual void rtp_done_buffering(void) {}; uint32_t m_rtptime_last; int m_recvd_pak; int m_recvd_pak_timeout; uint64_t m_recvd_pak_timeout_time; uint64_t m_last_realtime; format_list_t *m_fmt; int m_eof; int m_rtpinfo_set_from_pak; uint16_t m_next_seq; bool m_have_first_pak_ts; uint64_t m_first_pak_ts; uint32_t m_first_pak_rtp_ts; CPlayerSession *m_psptr; bool m_have_sync_info; rtcp_sync_t m_sync_info; }; class CRtpByteStream : public CRtpByteStreamBase { public: CRtpByteStream(const char *name, format_list_t *fmt, unsigned int rtp_pt, int ondemand, uint64_t tickpersec, rtp_packet **head, rtp_packet **tail, int rtp_seq_set, uint16_t rtp_base_seq, int rtp_ts_set, uint32_t rtp_base_ts, int rtcp_received, uint32_t ntp_frac, uint32_t ntp_sec, uint32_t rtp_ts); ~CRtpByteStream(); uint64_t start_next_frame(uint8_t **buffer, uint32_t *buflen, void **userdata); int skip_next_frame(uint64_t *ts, int *havesync, uint8_t **buffer, uint32_t *buflen, void **userdata = NULL); void used_bytes_for_frame(uint32_t bytes); int have_no_data(void); void flush_rtp_packets(void); void reset(void); protected: uint8_t *m_buffer; uint32_t m_buffer_len; uint32_t m_buffer_len_max; uint32_t m_bytes_used; }; class CAudioRtpByteStream : public CRtpByteStream { public: CAudioRtpByteStream(unsigned int rtp_pt, format_list_t *fmt, int ondemand, uint64_t tickpersec, rtp_packet **head, rtp_packet **tail, int rtp_seq_set, uint16_t rtp_base_seq, int rtp_ts_set, uint32_t rtp_base_ts, int rtcp_received, uint32_t ntp_frac, uint32_t ntp_sec, uint32_t rtp_ts); ~CAudioRtpByteStream(); int have_no_data(void); int check_rtp_frame_complete_for_payload_type(void); uint64_t start_next_frame(uint8_t **buffer, uint32_t *buflen, void **userdata); void reset(void); private: rtp_packet *m_working_pak; }; int add_rtp_packet_to_queue(rtp_packet *pak, rtp_packet **head, rtp_packet **tail, const char *name); #endif