📄 rfc3119_bytestream.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. 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 _WIN32DEFINE_MESSAGE_MACRO(mpa_message, "mparobust")#else#define mpa_message(loglevel, fmt...) message(loglevel, "mparobust", fmt)#endifCRfc3119RtpByteStream::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, pak->pd.rtp_pd_timestamp, 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -