www.pudn.com > RTP通用开发库(for Linux).rar > upcall.c


/*-------------------------------------------------------------------------
 * upcall.c - aligned, dataoffset, frameduration, framelength
 * 
 * This file contains upcall functions to decode information
 * necessary to extract MPEG-I and MPEG-II audio frames.
 * These functions are invoked by the synchronization layer of the RTP
 * library. 
 * See RFC 2250 and the MPEG standard for details on the MPEG encoding
 * and MPEG audio transport on RTP.
 *-------------------------------------------------------------------------
 */

#include 
#include "common.h"

/*-------------------------------------------------------------------------
 * aligned - returns true if the data within the RTP packet
 * begins on an MPEG frame boundry.
 *-------------------------------------------------------------------------
 */
bool aligned(struct rtp *prtp, int size) {
  
	unsigned short *mbz;
	unsigned short *offset;

	/*
	 * Dangerous -- dont check size for now.
	 */
	mbz = (short *) RTP_DATA(prtp);
	offset = mbz + 1;
	return (*offset == 0);
}

/*-------------------------------------------------------------------------
 * dataoffset - returns the position of the first byte of frame data
 * after the end of the standard RTP header.
 * MPEG audio always begins 4 bytes after the RTP header ends.
 *-------------------------------------------------------------------------
 */
int dataoffset(struct rtp *prtp, int size) {
	return 4;
}

/*-------------------------------------------------------------------------
 * frameduration - computes the duration in 1/90000s second of the frame
 * pointed to by pframe that is size octets long.
 *-------------------------------------------------------------------------
 */
mediatime_t frameduration(char *pframe, int size) {

  int	samprateindex;
  float samprate;
  int   samples;
  int   version;
  int	layer;

  /*
   * Determine version (I or II)
   */
  version = (pframe[1] & 0x8) >> 3;

  /* 
   * Determine layer (1, 2, or 3)
   */
  layer = (pframe[1] & 0x6) >> 1;
  layer = 4 - layer;

  /* 
   * Determine the sample rate.
   */
  samprateindex = (pframe[2] & 0xc) >> 2;
  samprate = s_freq[version][samprateindex] * 1000;

  /* 
   * Determine the number of samples in the frame.
   */
  if (layer == 1)
    samples = 384;
  else {
    if (version == 1) {
      samples = 1152;
    } 
    else {
      if (layer == 3) {
	samples = 576;
      }
      else {
	samples = 1152;
      }
    }
  }
  
  /*
   * Convert to 90000ths of a second.
   */
  return ((90000 * samples) / samprate);
}

/*-------------------------------------------------------------------------
 * framelength - returns the length, in octets, of the frame pointed to by
 * pframe.
 *-------------------------------------------------------------------------
 */
int framelength(char *pframe, int size) {

	int	version, rv;
	int	layer;
	int	padding;
	float	bitrt;
	float samprate;
	int	bitrateindex;
	int	samprateindex;

	/*
	 * Determine the MPEG version (I or II)
	 */
	version = (pframe[1] & 0x8) >> 3;
      
	/*
	 * Determine the layer (1, 2, or 3)
	 */
	layer = (pframe[1] & 0x6) >> 1;
	layer = 4 - layer;

	/*
	 * Determine if padding is present.
	 */
	padding = (pframe[2] & 0x2) >> 1;

	/*
	 * Determine the bitrate.
	 */
	bitrateindex = (pframe[2] & 0xf0) >> 4;
	bitrt = bitrate[version][layer-1][bitrateindex] * 1000;

	/* 
	 * Determine the sample rate.
	 */
	samprateindex = (pframe[2] & 0xc) >> 2;
	samprate = s_freq[version][samprateindex] * 1000;

	if (layer == 1) 
		rv =  (int) ((((((12 * bitrt) / samprate)) * 4) / (version == 0 ? 2.0 : 1.0)) + padding);
	else
		rv = (int) ((((144 * bitrt) / samprate) / (version == 0 ? 2.0 : 1.0)) + padding);     

	return rv;
}