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

📄 isma_rtp_plugin.cpp

📁 网络MPEG4IP流媒体开发源代码
💻 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. 2001.  All Rights Reserved. *  * Contributor(s):  *              Bill May        wmay@cisco.com */#include "isma_rtp_plugin.h"#include "mp4util/mpeg4_audio_config.h"#include "rtp/rtp.h"//#define DEBUG_ISMA_AAC#define isma_message iptr->m_vft->log_msgstatic const char *ismartp="ismartp";static rtp_check_return_t check (lib_message_func_t msg, 				 format_list_t *fmt, 				 uint8_t rtp_payload_type){  if (fmt == NULL || fmt->rtpmap == NULL)     return RTP_PLUGIN_NO_MATCH;  if (strcasecmp(fmt->rtpmap->encode_name, "mpeg4-generic") != 0) {    return RTP_PLUGIN_NO_MATCH;  }  fmtp_parse_t *fmtp;  int len;  fmtp = parse_fmtp_for_mpeg4(fmt->fmt_param, msg);  if (fmtp == NULL) return RTP_PLUGIN_NO_MATCH;  len = fmtp->size_length;  free_fmtp_parse(fmtp);  if (len == 0) {    return RTP_PLUGIN_NO_MATCH;  }  return RTP_PLUGIN_MATCH;}static isma_frame_data_t *get_frame_data (isma_rtp_data_t *iptr) {  isma_frame_data_t *pak;  if (iptr->m_frame_data_free == NULL) {    pak = (isma_frame_data_t *)malloc(sizeof(isma_frame_data_t));    if (pak == NULL) return NULL;  } else {    pak = iptr->m_frame_data_free;    iptr->m_frame_data_free = pak->frame_data_next;  }  pak->frame_data_next = NULL;  pak->last_in_pak = 0;  return (pak);}/* * Isma rtp bytestream has a potential set of headers at the beginning * of each rtp frame.  This can interleave frames in different packets */rtp_plugin_data_t *isma_rtp_plugin_create (format_list_t *media_fmt,					   uint8_t rtp_payload_type, 					   rtp_vft_t *vft,					   void *ifptr){  isma_rtp_data_t *iptr;  fmtp_parse_t *fmtp;  iptr = MALLOC_STRUCTURE(isma_rtp_data_t);  memset(iptr, 0, sizeof(isma_rtp_data_t));  iptr->m_vft = vft;  iptr->m_ifptr = ifptr;  iptr->m_rtp_packet_mutex = SDL_CreateMutex();#ifdef ISMA_RTP_DUMP_OUTPUT_TO_FILE  iptr->m_outfile = fopen("isma.aac", "w");#endif  iptr->m_frame_data_head = NULL;  iptr->m_frame_data_on = NULL;  iptr->m_frame_data_free = NULL;  isma_frame_data_t *p;  for (iptr->m_frame_data_max = 0; iptr->m_frame_data_max < 25; iptr->m_frame_data_max++) {    p = (isma_frame_data_t *)malloc(sizeof(isma_frame_data_t));    p->frame_data_next = iptr->m_frame_data_free;    iptr->m_frame_data_free = p;  }  fmtp = parse_fmtp_for_mpeg4(media_fmt->fmt_param, iptr->m_vft->log_msg);  mpeg4_audio_config_t audio_config;  decode_mpeg4_audio_config(fmtp->config_binary,			    fmtp->config_binary_len,			    &audio_config);  if (audio_object_type_is_aac(&audio_config)) {    iptr->m_rtp_ts_add = audio_config.codec.aac.frame_len_1024 != 0 ? 1024 : 960;  } else {    iptr->m_rtp_ts_add = audio_config.codec.celp.samples_per_frame;    isma_message(LOG_DEBUG, ismartp, "celp spf is %d", iptr->m_rtp_ts_add);  }  iptr->m_rtp_ts_add = (iptr->m_rtp_ts_add * media_fmt->rtpmap->clock_rate) /    audio_config.frequency;  isma_message(LOG_DEBUG, ismartp,	       "Rtp ts add is %d (%d %d)", iptr->m_rtp_ts_add,	       media_fmt->rtpmap->clock_rate, 	       audio_config.frequency);  iptr->m_fmtp = fmtp;  iptr->m_min_first_header_bits = iptr->m_fmtp->size_length + iptr->m_fmtp->index_length;  iptr->m_min_header_bits = iptr->m_fmtp->size_length + iptr->m_fmtp->index_delta_length;  if (iptr->m_fmtp->CTS_delta_length > 0) {    iptr->m_min_header_bits++;    iptr->m_min_first_header_bits++;  }  if (iptr->m_fmtp->DTS_delta_length > 0) {    iptr->m_min_header_bits++;    iptr->m_min_first_header_bits++;  }  isma_message(LOG_DEBUG, ismartp, "min headers are %d %d", iptr->m_min_first_header_bits,	       iptr->m_min_header_bits);  iptr->m_min_header_bits += iptr->m_fmtp->auxiliary_data_size_length;  iptr->m_min_first_header_bits += iptr->m_fmtp->auxiliary_data_size_length;  iptr->m_frag_reass_buffer = NULL;  iptr->m_frag_reass_size_max = 0;  return (&iptr->plug);}static void isma_rtp_destroy (rtp_plugin_data_t *pifptr){  isma_rtp_data_t *iptr = (isma_rtp_data_t *)pifptr;#ifdef ISMA_RTP_DUMP_OUTPUT_TO_FILE  fclose(iptr->m_outfile);#endif  isma_frame_data_t *p;    if (iptr->m_frag_reass_buffer != NULL) {    free(iptr->m_frag_reass_buffer);    iptr->m_frag_reass_buffer = NULL;  }  if (iptr->m_frame_data_on != NULL) {    iptr->m_frame_data_on->frame_data_next = iptr->m_frame_data_head;    iptr->m_frame_data_head = iptr->m_frame_data_on;    iptr->m_frame_data_on = NULL;  }  while (iptr->m_frame_data_free != NULL) {    p = iptr->m_frame_data_free;    iptr->m_frame_data_free = p->frame_data_next;    free(p);  }  while (iptr->m_frame_data_head != NULL) {    p = iptr->m_frame_data_head;    // if fragmented frame, free all frag_data    if (p->is_fragment == 1) {      isma_frag_data_t * q = p->frag_data;      while (q != NULL) {	p->frag_data = q->frag_data_next;	free(q);	q = p->frag_data;      }    }    iptr->m_frame_data_head = p->frame_data_next;    free(p);  }  if (iptr->m_fmtp != NULL) {    free_fmtp_parse(iptr->m_fmtp);  }  free(iptr);}static int insert_frame_data (isma_rtp_data_t *iptr, 			      isma_frame_data_t *frame_data){  SDL_LockMutex(iptr->m_rtp_packet_mutex);  if (iptr->m_frame_data_head == NULL) {    iptr->m_frame_data_head = frame_data;  } else {    int32_t diff;    isma_frame_data_t *p, *q;    q = NULL;    p = iptr->m_frame_data_head;    do {      diff = frame_data->rtp_timestamp - p->rtp_timestamp;      if (diff == 0) {	isma_message(LOG_ERR, ismartp, "Duplicate timestamp of %x found in RTP packet",		     frame_data->rtp_timestamp);	isma_message(LOG_DEBUG, ismartp,		     "Seq number orig %d new %d", 		     p->pak->rtp_pak_seq, frame_data->pak->rtp_pak_seq); 	// if fragmented frame, free all frag_data	if (frame_data->is_fragment == 1) {	  isma_frag_data_t * p = NULL;	  while ((p = frame_data->frag_data) != NULL) {	    frame_data->frag_data = p->frag_data_next;	    free(p);	  }	}	// put frame_data on free list	frame_data->frame_data_next = iptr->m_frame_data_free;	iptr->m_frame_data_free = frame_data;	SDL_UnlockMutex(iptr->m_rtp_packet_mutex);	return 1;      } else if (diff < 0) {	if (q == NULL) {	  frame_data->frame_data_next = iptr->m_frame_data_head;	  iptr->m_frame_data_head = frame_data;	} else {	  q->frame_data_next = frame_data;	  frame_data->frame_data_next = p;	}	SDL_UnlockMutex(iptr->m_rtp_packet_mutex);	return 0;      }      q = p;      p = p->frame_data_next;    } while (p != NULL);    // insert at end;    q->frame_data_next = frame_data;  }  SDL_UnlockMutex(iptr->m_rtp_packet_mutex);  return 0;}static void get_au_header_bits (isma_rtp_data_t *iptr){  uint32_t temp;  if (iptr->m_fmtp->CTS_delta_length > 0) {    iptr->m_header_bitstream.getbits(1, &temp);    if (temp > 0) {      iptr->m_header_bitstream.getbits(iptr->m_fmtp->CTS_delta_length, &temp);    }  }  if (iptr->m_fmtp->DTS_delta_length > 0) {    iptr->m_header_bitstream.getbits(1, &temp);    if (temp > 0) {      iptr->m_header_bitstream.getbits(iptr->m_fmtp->DTS_delta_length, &temp);    }  }}// check where need to lock static void cleanup_frag (isma_rtp_data_t *iptr, 			  isma_frame_data_t * frame_data){  // free all frag_data for this frame  isma_frag_data_t * p = NULL;  while ((p = frame_data->frag_data) != NULL) {    frame_data->frag_data = p->frag_data_next;    free(p);  }   // now put frame_data back on free list  SDL_LockMutex(iptr->m_rtp_packet_mutex);  frame_data->frame_data_next = iptr->m_frame_data_free;  iptr->m_frame_data_free = frame_data;  SDL_UnlockMutex(iptr->m_rtp_packet_mutex);  return;}// Frame is fragmented.// Process next RTP paks until have the entire frame.// Paks will be in order in the queue, but maybe some missing?// So if process pkt w/ Mbit set (last of fragm) and total < frameLength// ignore pkt.// Insert frame data only after got all fragments for the frame.static int process_fragment (isma_rtp_data_t *iptr, 			     rtp_packet *pak, 			     isma_frame_data_t *frame_data){  uint16_t seq = pak->rtp_pak_seq;   uint32_t ts = pak->rtp_pak_ts;  isma_frag_data_t *cur = NULL;  int read_mBit = 0;  uint32_t total_len = 0;   frame_data->is_fragment = 1;  do {    if (read_mBit == 1) {      // get rid of frame_data - last frag seen but total length wrong      cleanup_frag(iptr, frame_data);      isma_message(LOG_ERR, ismartp, "Error processing frag: early mBit");      return (1);     }    if (pak == NULL) {      cleanup_frag(iptr, frame_data);      isma_message(LOG_ERR, ismartp, "Error processing frag: not enough packets");      return (1);    }    // check if ts and rtp seq numbers are ok, and lengths match    if (ts != pak->rtp_pak_ts) {      cleanup_frag(iptr, frame_data);      isma_message(LOG_ERR, ismartp, 		   "Error processing frag: wrong ts: ts= %x, pak->ts = %x", 		   ts, pak->rtp_pak_ts);      return (1);    }    if (seq != pak->rtp_pak_seq) {      cleanup_frag(iptr, frame_data);      isma_message(LOG_ERR, ismartp, "Error processing frag: wrong seq num");      return (1);    }    // insert fragment info    isma_frag_data_t *p = (isma_frag_data_t *)      malloc(sizeof(isma_frag_data_t));    if (p == NULL) {      isma_message(LOG_ERR, ismartp, "Error processing frag: can't malloc");      iptr->m_vft->free_pak(pak);      return (1);    }    if (cur == NULL) {      frame_data->frag_data = p;      cur = p;		    } else {      cur->frag_data_next = p;      cur = p;    }    cur->frag_data_next = NULL;    cur->pak = pak;     // length in bits    uint16_t header_len = ntohs(*(unsigned short *)pak->rtp_data);    iptr->m_header_bitstream.init(&pak->rtp_data[sizeof(uint16_t)], header_len);    // frag_ptr should just point to beginning of data in pkt    uint32_t header_len_bytes = ((header_len + 7) / 8) + sizeof(uint16_t);    cur->frag_ptr =  &pak->rtp_data[header_len_bytes];    cur->frag_len = pak->rtp_data_len - header_len_bytes;    // if aux data, move frag pointer    if (iptr->m_fmtp->auxiliary_data_size_length > 0) {      iptr->m_header_bitstream.byte_align();      uint32_t aux_len;      iptr->m_header_bitstream.getbits(iptr->m_fmtp->auxiliary_data_size_length, &aux_len);      aux_len = (aux_len + 7) / 8;      cur->frag_ptr += aux_len;      cur->frag_len -= aux_len;    }    total_len += cur->frag_len;#ifdef DEBUG_ISMA_RTP_FRAGS    isma_message(LOG_DEBUG, ismartp, 		 "rtp seq# %d, fraglen: %d, ts: %x", 		 pak->seq, cur->frag_len, pak->ts);#endif	    seq = pak->rtp_pak_seq + 1;    if (pak->rtp_pak_m)       read_mBit = 1;    iptr->m_vft->remove_from_list(iptr->m_ifptr, pak);    pak = iptr->m_vft->get_next_pak(iptr->m_ifptr, NULL, 0);  } while (total_len < frame_data->frame_len);  // insert frame and return  int error = insert_frame_data(iptr, frame_data);  frame_data->last_in_pak = 1; // only one frame in pak  // no need to remove pkt from queue, done at the end of do-while

⌨️ 快捷键说明

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