⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg3_rtp_bytestream.cpp

📁 网络MPEG4IP流媒体开发源代码
💻 CPP
字号:
/* * 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. 2001.  All Rights Reserved. *  * Contributor(s):  *              Bill May        wmay@cisco.com */#include "systems.h"#include <rtp/rtp.h>#include <rtp/memory.h>#include <sdp/sdp.h> // for NTP_TO_UNIX_TIME#include "mpeg3_rtp_bytestream.h"#include "our_config_file.h"//#define DEBUG_RTP_PAKS 1//#define DEBUG_MPEG3_RTP_TIME 1#ifdef _WIN32DEFINE_MESSAGE_MACRO(rtp_message, "rtpbyst")#else#define rtp_message(loglevel, fmt...) message(loglevel, "rtpbyst", fmt)#endifstatic rtp_packet *end_of_pak (rtp_packet *start){  while (start->rtp_next->rtp_pak_ts == start->rtp_pak_ts)     start = start->rtp_next;  return start;}CMpeg3RtpByteStream::CMpeg3RtpByteStream(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) :  CRtpByteStream("mpeg3", fmt, rtp_pt, ondemand, tickpersec, head, tail,		 rtp_seq_set, rtp_base_seq, rtp_ts_set, rtp_base_ts, 		 rtcp_received, ntp_frac, ntp_sec, rtp_ts){}uint64_t CMpeg3RtpByteStream::start_next_frame (uint8_t **buffer, 						uint32_t *buflen,						void **ud){  uint16_t seq = 0;  uint32_t ts = 0, outts;  uint64_t timetick;  uint64_t pak_ts = 0;  int first = 0;  int finished = 0;  rtp_packet *rpak;  int32_t diff;  int correct_hdr;  int dropped_seq;  diff = m_buffer_len - m_bytes_used;  if (diff > 2) {    // Still bytes in the buffer...    *buffer = m_buffer + m_bytes_used;    *buflen = diff;#ifdef DEBUG_RTP_PAKS    rtp_message(LOG_DEBUG, "%s Still left - %d bytes", m_name, *buflen);#endif    return (m_last_realtime);  }  int frame_type;  m_buffer_len = 0;  dropped_seq = 0;  while (finished == 0) {    rpak = m_head;    if (rpak == NULL) {      *buffer = NULL;      return 0;    }    remove_packet_rtp_queue(rpak, 0);    correct_hdr = 1;    if (m_next_seq != rpak->rtp_pak_seq) {      correct_hdr = 0;      rtp_message(LOG_INFO, "%s missing rtp sequence - should be %u is %u", 		  m_name, m_next_seq, rpak->rtp_pak_seq);      first = 0;    } else {      if (first == 0) {	ts = rpak->rtp_pak_ts;	pak_ts = rpak->pd.rtp_pd_timestamp;	first = 1;      } else {	if (ts != rpak->rtp_pak_ts) {	  rtp_message(LOG_INFO, 		      "%s timestamp error - seq %u should be %x is %x", 		      m_name, seq, ts, rpak->rtp_pak_ts);	  correct_hdr = 0;	}	ts = rpak->rtp_pak_ts;      }    }    if (correct_hdr == 0) {      m_buffer_len = 0;    } else {      dropped_seq = 1;    }    m_next_seq = rpak->rtp_pak_seq + 1; // handles wrap correctly    uint8_t *from;    uint32_t len;    m_skip_on_advance_bytes = 4;    if ((*rpak->rtp_data & 0x4) != 0) {      m_skip_on_advance_bytes = 8;      if ((rpak->rtp_data[4] & 0x40) != 0) {      }    }    frame_type = rpak->rtp_data[2] & 0x7;    from = (uint8_t *)rpak->rtp_data + m_skip_on_advance_bytes;    len = rpak->rtp_data_len - m_skip_on_advance_bytes;    if ((m_buffer_len + len) > m_buffer_len_max) {      // realloc      m_buffer_len_max = m_buffer_len + len + 1024;      m_buffer = (uint8_t *)realloc(m_buffer, m_buffer_len_max);    }    memcpy(m_buffer + m_buffer_len, 	   from,	   len);    m_buffer_len += len;      if (rpak->rtp_pak_m == 1) {      finished = 1;    }    xfree(rpak);  }  m_bytes_used = 0;  *buffer = m_buffer + m_bytes_used;  *buflen = m_buffer_len - m_bytes_used;#ifdef DEBUG_RTP_PAKS  rtp_message(LOG_DEBUG, "%s buffer len %d", m_name, m_buffer_len);#endif  if (dropped_seq || m_have_mpeg_ip_ts == 0) {    outts = calc_this_ts_from_future(frame_type, ts);  } else {    if (frame_type == 3) {      // B frame      outts = ts + m_rtp_frame_add;    } else {      outts = m_mpeg_ip_ts + m_rtp_frame_add;      m_mpeg_ip_ts = ts;    }  }#ifdef DEBUG_MPEG3_RTP_TIME  rtp_message(LOG_DEBUG, "frame type %d pak ts %u out ts %u", frame_type, 	      ts, outts);#endif  if (m_rtpinfo_set_from_pak != 0) {    if (outts < m_base_rtp_ts) {      m_base_rtp_ts = outts;    }    m_rtpinfo_set_from_pak = 0;  }  m_ts = outts;  timetick = rtp_ts_to_msec(outts, pak_ts, m_wrap_offset);    return (timetick);}uint32_t CMpeg3RtpByteStream::calc_this_ts_from_future (int frame_type,						   uint32_t pak_ts){  int new_frame_type;  uint32_t outts = 0;  m_have_mpeg_ip_ts = 0;  if (frame_type >= 3) {    // B frame - ts is always pak_ts + 1 frame time    return pak_ts + m_rtp_frame_add;  }  SDL_LockMutex(m_rtp_packet_mutex);  if (m_head->rtp_pak_seq != m_next_seq) {    outts = m_head->rtp_pak_ts - m_rtp_frame_add; // not accurate, but close enuff  } else {    new_frame_type = m_head->rtp_data[2] & 0x7;    if (new_frame_type >= 3) {      // I/P frame followed by B frame - take the B frame's timestamp      outts = m_head->rtp_pak_ts;      m_mpeg_ip_ts = pak_ts;      m_have_mpeg_ip_ts = 1;    }  else if (frame_type == 2 ||		(frame_type == 1 && new_frame_type == 1)) {    // I/P frame followed by I frame, P frame followed by I or P frame      outts = pak_ts - (m_head->rtp_pak_ts - pak_ts);      m_mpeg_ip_ts = pak_ts;      m_have_mpeg_ip_ts = 1;    }   }  SDL_UnlockMutex(m_rtp_packet_mutex);  return outts;}							int CMpeg3RtpByteStream::skip_next_frame (uint64_t *pts, int *hasSyncFrame,					  uint8_t **buffer, 					  uint32_t *buflen, 					  void **ud){  uint64_t ts;  *hasSyncFrame = -1;  // we don't know if we have a sync frame  m_buffer_len = m_bytes_used = 0;  if (m_head == NULL) return 0;  ts = m_head->rtp_pak_ts;  do {    remove_packet_rtp_queue(m_head, 1);  } while (m_head != NULL && m_head->rtp_pak_ts == ts);  if (m_head == NULL) return 0;  init();  m_buffer_len = m_bytes_used = 0;  ts = start_next_frame(buffer, buflen, NULL);  *pts = ts;  return (1);}int CMpeg3RtpByteStream::have_no_data (void){  rtp_packet *temp, *first;  if (m_head == NULL) return TRUE;  first = temp = m_head;  int count = 0;  SDL_LockMutex(m_rtp_packet_mutex);  do {    if (temp->rtp_pak_m == 1) {      count++;      if (count > 1) {	SDL_UnlockMutex(m_rtp_packet_mutex);	return FALSE;      }    }    temp = temp->rtp_next;  } while (temp != NULL && temp != first);  SDL_UnlockMutex(m_rtp_packet_mutex);  return TRUE;}void CMpeg3RtpByteStream::rtp_done_buffering (void) {  rtp_packet *p, *q;  int had_b;  SDL_LockMutex(m_rtp_packet_mutex);  m_next_seq = m_head->rtp_pak_seq;#ifdef DEBUG_MPEG3_RTP_TIME   p = m_head;  while (p->rtp_next != m_head) {    rtp_message(LOG_DEBUG, "seq %u ts %u %x %x %x %x",		p->rtp_pak_seq,		p->rtp_pak_ts, 		p->rtp_data[0],		p->rtp_data[1],		p->rtp_data[2],		p->rtp_data[3]);    p = p->rtp_next;  }#endif  p = m_head;  had_b = 0;  do {    q = end_of_pak(p);    if ((q->rtp_data[2] & 0x7) == 3) {      // B frame       had_b = 1;      if ((((q->rtp_pak_seq + 1) & 0xffff) == q->rtp_next->rtp_pak_seq) &&	  ((q->rtp_next->rtp_data[2] & 0x7) == 3)) {	// 2 consec b frames	m_rtp_frame_add  = q->rtp_next->rtp_pak_ts - p->rtp_pak_ts;#ifdef DEBUG_MPEG3_RTP_TIME	rtp_message(LOG_DEBUG, "seq %u %u data %x %x %x", 		    q->rtp_pak_seq, q->rtp_next->rtp_pak_seq,		    p->rtp_data[2],		    q->rtp_data[2], q->rtp_next->rtp_data[2]);	rtp_message(LOG_DEBUG, "2 consec b frames %d %d %d", 		    m_rtp_frame_add,		    p->rtp_pak_ts, q->rtp_pak_ts);#endif	SDL_UnlockMutex(m_rtp_packet_mutex);	return;      }    }    p = q->rtp_next;  }  while (p != m_head);  rtp_message(LOG_DEBUG, "mpeg3 - no b frames found in buffer");  if (had_b == 0) {    // no b frames     p = end_of_pak(m_head);    while (p != m_head) {      q = end_of_pak(p->rtp_next);      if (((q->rtp_pak_seq + 1) & 0xffff) == q->rtp_next->rtp_pak_seq) {	q = q->rtp_next;	m_rtp_frame_add  = q->rtp_pak_ts - p->rtp_pak_ts;	SDL_UnlockMutex(m_rtp_packet_mutex);	return;      }      p = q->rtp_next;    }  }  rtp_message(LOG_DEBUG, "mpeg3 - flushing packets");  m_buffering = 0;  SDL_UnlockMutex(m_rtp_packet_mutex);  flush_rtp_packets();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -