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

📄 rfc3119_bytestream.cpp

📁 jpeg and mpeg 编解码技术源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 * 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. 2002.  All Rights Reserved.
 * 
 * Contributor(s): 
 *              Bill May        wmay@cisco.com
 */
/*
 * rfc3119_bytestream.cpp - an implemention of rfc 3119
 */
#include "systems.h"
#include <rtp/rtp.h>
#include <rtp/memory.h>
#include <sdp/sdp.h> // for NTP_TO_UNIX_TIME
#include "rfc3119_bytestream.h"
#include <mp3util/MP3Internals.hh>

//#define DEBUG_3119 1
//#define DEBUG_3119_INTERLEAVE 1
#ifdef _WIN32
DEFINE_MESSAGE_MACRO(mpa_message, "mparobust")
#else
#define mpa_message(loglevel, fmt...) message(loglevel, "mparobust", fmt)
#endif

CRfc3119RtpByteStream::CRfc3119RtpByteStream (unsigned int rtp_pt,
					      format_list_t *fmt,
					      int ondemand,
					      uint64_t tps,
					      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("mparobust", fmt, rtp_pt, ondemand, tps, head, tail, 
		     rtp_seq_set, rtp_base_seq, rtp_ts_set, rtp_base_ts,
		     rtcp_received, ntp_frac, ntp_sec, rtp_ts)
{
#ifdef ISMA_RTP_DUMP_OUTPUT_TO_FILE
  m_outfile = fopen("isma.aac", "w");
#endif
  m_adu_data_free = NULL;
  m_deinterleave_list = NULL;
  m_ordered_adu_list = NULL;
  m_pending_adu_list = NULL;

  adu_data_t *p;
  for (int ix = 0; ix < 25; ix++) {
    p = MALLOC_STRUCTURE(adu_data_t);
    p->next_adu = m_adu_data_free;
    m_adu_data_free = p;
  }
  m_rtp_ts_add = 0;
  m_recvd_first_pak = 0;
  m_got_next_idx = 0;
  m_mp3_frame = NULL;
  m_mp3_frame_size = 0;
}

CRfc3119RtpByteStream::~CRfc3119RtpByteStream (void)
{
#ifdef ISMA_RTP_DUMP_OUTPUT_TO_FILE
  fclose(m_outfile);
#endif
  adu_data_t *p;
#if 0
  if (m_frag_reass_buffer != NULL) {
    free(m_frag_reass_buffer);
    m_frag_reass_buffer = NULL;
  }
#endif

  dump_adu_list(m_deinterleave_list);
  m_deinterleave_list = NULL;
  dump_adu_list(m_ordered_adu_list);
  m_ordered_adu_list = NULL;
  dump_adu_list(m_pending_adu_list);
  m_pending_adu_list = NULL;

  while (m_adu_data_free != NULL) {
    p = m_adu_data_free;
    m_adu_data_free = p->next_adu;
    free(p);
  }
}

void CRfc3119RtpByteStream::insert_interleave_adu (adu_data_t *adu)
{
  adu_data_t *p, *q;
#ifdef DEBUG_3119_INTERLEAVE
  mpa_message(LOG_DEBUG, "inserting interleave %d %d %d", adu->aduDataSize,
	      adu->cyc_ct, adu->interleave_idx);
#endif
  SDL_LockMutex(m_rtp_packet_mutex);
  
  if (m_deinterleave_list == NULL) {
    m_got_next_idx = 0;
    m_deinterleave_list = adu;
  } else {
    q = NULL;
    p = m_deinterleave_list;
    if (adu->cyc_ct != p->cyc_ct) {
      m_got_next_idx = 1;
      do {
	q = p;
	p = p->next_adu;
      } while (p != NULL && p->cyc_ct != adu->cyc_ct);
      if (p == NULL) {
	q->next_adu = adu;
	SDL_UnlockMutex(m_rtp_packet_mutex);
	return;
      } 
    }
    while (p != NULL && p->interleave_idx < adu->interleave_idx) {
      q = p;
      p = p->next_adu;
    }
    q->next_adu = adu;
    adu->next_adu = p;
  }
  SDL_UnlockMutex(m_rtp_packet_mutex);
}

int CRfc3119RtpByteStream::insert_processed_adu (adu_data_t *adu)
{
#ifdef DEBUG_3119
  mpa_message(LOG_DEBUG, "inserting processed %d", adu->aduDataSize);
#endif
  SDL_LockMutex(m_rtp_packet_mutex);
  if (m_ordered_adu_list == NULL) {
    m_ordered_adu_list = adu;
  } else {
    int32_t diff;
    adu_data_t *p, *q;
    q = NULL;
    p = m_ordered_adu_list;

    do {
      diff = adu->timestamp - p->timestamp;
      if (diff == 0) {
	mpa_message(LOG_ERR, "Duplicate timestamp of "LLU" found in RTP packet",
		    adu->timestamp);
	mpa_message(LOG_DEBUG, 
		     "Seq number orig %d new %d", 
		     p->pak->rtp_pak_seq, adu->pak->rtp_pak_seq); 
	mpa_message(LOG_ERR, "Dumping all processed packets");

	
	// put frame_data on free list
	if (adu->last_in_pak == 0) {
	  free_adu(adu);
	} else {
	  mpa_message(LOG_ERR, "Im lazy - duplicate ADU leads to memory leak");
	}
	SDL_UnlockMutex(m_rtp_packet_mutex);
	return -1;
      } else if (diff < 0) {
#ifdef DEBUG_3119
	mpa_message(LOG_DEBUG, "Inserting in front of ts %llu", p->timestamp);
#endif
	if (q == NULL) {
	  adu->next_adu = m_ordered_adu_list;
	  m_ordered_adu_list = adu;
	} else {
	  q->next_adu = adu;
	  adu->next_adu = p;
	}
	SDL_UnlockMutex(m_rtp_packet_mutex);
	return 0;
      }
      q = p;
      p = p->next_adu;
    } while (p != NULL);
    // insert at end;
    q->next_adu = adu;

  }
  SDL_UnlockMutex(m_rtp_packet_mutex);
  return 0;
}

void CRfc3119RtpByteStream::process_packet (void)
{
  rtp_packet *pak;
  uint64_t pak_ts;
  int adu_offset;
  adu_data_t *prev_adu;
  int thisAduSize;

  do {
    /*
     * Take packet off list.  Loop through, looking for ADU headersize
     * packets
     */
    pak = m_head;
    if (pak != NULL) {
      remove_packet_rtp_queue(m_head, 0);
      pak_ts = rtp_ts_to_msec(pak->rtp_pak_ts, m_wrap_offset);
      adu_offset = 0;
      prev_adu = NULL;

#ifdef DEBUG_3119
      mpa_message(LOG_DEBUG, "Process pak seq %d", pak->rtp_pak_seq);
#endif

      while (pak != NULL && adu_offset < pak->rtp_data_len) {
	uint8_t *ptr;
	ptr = (uint8_t *)(pak->rtp_data + adu_offset);
	if ((*ptr & 0x80) == 0x80) {
	  // first one has a c field of 1 - that's bad
	  xfree(pak);
	  pak = NULL;
	  adu_offset = 0;
	} else {
	  /*
	   * Get a new adu - start loading the data
	   */
	  adu_data_t *adu = get_adu_data();

	  adu->pak = pak;
	  adu->next_adu = NULL;
	  adu->last_in_pak = 0;
	  adu->freeframe = 0;
	  if (adu_offset == 0) {
	    adu->first_in_pak = 1;
	    adu->timestamp = pak_ts;
	  } else {
	    adu->first_in_pak = 0;
	  }
	  /*
	   * Read the ADU header.  It will be 1 byte or 2
	   */
	  if ((*ptr & 0x40) == 0) {
	    // 1 byte header
	    adu->frame_ptr = ptr + 1;
	    adu->aduDataSize = *ptr & 0x3f;
	    adu_offset++;
	  } else {
	    // 2 byte header
	    adu->aduDataSize = ((*ptr & 0x3f) << 8) + ptr[1];
	    adu->frame_ptr = ptr + 2;
	    adu_offset += 2;
	  }
	  /*
	   * See if we're past the end of the packet
	   */
	  thisAduSize = adu->aduDataSize;
	  if (adu_offset + adu->aduDataSize > pak->rtp_data_len) {
	    // have a fragment here...
	    // malloc a frame pointer, and copy the rest... 
	    uint16_t seq = pak->rtp_pak_seq;
	    uint8_t *to, *from;
	    to = (uint8_t *)malloc(adu->aduDataSize);
	    int copied = pak->rtp_data_len - adu_offset;
	    memcpy(to, adu->frame_ptr, copied);
	    if (prev_adu != NULL) {
	      prev_adu->last_in_pak = 1;
	    } else {
	      xfree(pak);
	    }
	    adu->frame_ptr = to;
	    adu->freeframe = 1;
	    to += copied;
	    while (m_head != NULL && 
		   m_head->rtp_pak_seq == seq + 1 && 
		   (*m_head->rtp_data & 0x80) == 0x80 && 
		   copied < adu->aduDataSize) {
	      uint32_t bytes;
	      pak = m_head;
	      remove_packet_rtp_queue(m_head, 0);
	      ptr = (uint8_t *)pak->rtp_data;
	      if ((*ptr & 0x40) == 0) {
		// 1 byte header
		bytes = *ptr & 0x3f;
		from = ptr++;
	      } else {
		// 2 byte header
		bytes = ((*ptr & 0x3f) << 8) + ptr[1];
		from = ptr + 2;
	      }
	      memcpy(to, from, bytes);
	      copied += bytes;
	      to += bytes;
	      seq++;
	      adu_offset = 0;
	      pak = NULL;
	    }
	    if (copied < adu->aduDataSize) {
	      free_adu(adu);
	      continue;
	    }
	  } else {
	    /*
	     * adu_offset now points past the end of this adu
	     */
	    adu_offset += adu->aduDataSize;
	    if (adu_offset >= pak->rtp_data_len) {
	      adu->last_in_pak = 1;
	    }
	  }

	  /*
	   * Calculate the interleave index and the cyc_ct count
	   * Fill in those values with all 1's
	   */
	  adu->interleave_idx = *adu->frame_ptr;
	  adu->cyc_ct = *(adu->frame_ptr + 1) >> 5;
	  adu->frame_ptr[0] = 0xff;
	  adu->frame_ptr[1] |= 0xe0;

	  /*
	   * Decode the mp3 header
	   */
	  adu->mp3hdr = MP4AV_Mp3HeaderFromBytes(adu->frame_ptr);
	  adu->framesize = MP4AV_Mp3GetFrameSize(adu->mp3hdr);

	  /*
	   * Headersize, sideInfoSize and aduDataSize 
	   */
	  adu->headerSize = 4;
	  adu->sideInfoSize = MP4AV_Mp3GetSideInfoSize(adu->mp3hdr);

	  adu->aduDataSize -= (adu->headerSize + adu->sideInfoSize);

	  /*
	   * Calculate the timestamp add
	   */
	  if (m_rtp_ts_add == 0) {
	    m_rtp_ts_add = 
	      ( 1000 * MP4AV_Mp3GetHdrSamplingWindow(adu->mp3hdr));

	    m_rtp_ts_add /= MP4AV_Mp3GetHdrSamplingRate(adu->mp3hdr);
	  }
	
	  // here we make a few decisions as to where the packet should
	  // go.
	  // Look at first packet.  If it's got interleave, we're interleaved
	  // if not, set up the timestamp, put it in the ordered_adu_list.
	  // (Don't set recvd_first pak).  If it's the 2nd, and not interleaved,
	  // leave the first, go on non-interleaved
	  // If the first isn't, and the 2nd is, move the first to the
	  // m_deinterleave_list, put the 2nd on the deinterleave list, 
	  // continue.
	  // If not the first, put on the interleaved or deinterleaved list.
	  int insert_interleaved = 0;

	  if (m_recvd_first_pak == 0) {
	    if (adu->interleave_idx == 0xff &&
		adu->cyc_ct == 0x7) {
	      /*
	       * Have an packet all 1's.  It's either the last of the
	       * sequence for interleave, or indicates no interleave.
	       * Put it on the ordered list if there's nothing there.
	       * If there is something on the ordered list, we're not doing
	       * interleaved.
	       */
	      if (m_ordered_adu_list == NULL) {
		insert_interleaved = 0;
	      } else {
		// this is the 2nd packet with the regular
		// header - we're not doing interleaved
		insert_interleaved = 0;
		m_recvd_first_pak = 1;
		m_have_interleave = 0;
	      }
	    } else {
	      /*
	       * Have an interleaved packet
	       * If there was something on the ordered list, move it to 
	       * the deinterleaved list
	       */
	      m_recvd_first_pak = 1;
	      if (m_ordered_adu_list != NULL) {
		m_deinterleave_list = m_ordered_adu_list;
		m_ordered_adu_list = NULL;
	      } 
	      m_have_interleave = 1;
	      insert_interleaved = 1;
	      mpa_message(LOG_INFO, "mpa robust format is interleaved");
	    }
	  } else {
	    insert_interleaved = m_have_interleave;
	  }

	  adu->backpointer =  MP4AV_Mp3GetAduOffset(adu->frame_ptr, 
						    thisAduSize);

	  if (insert_interleaved) {
	    insert_interleave_adu(adu);
	  } else {

⌨️ 快捷键说明

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