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

📄 sdp_decode.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * 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. 2000, 2001.  All Rights Reserved.
 * 
 * Contributor(s): 
 *              Bill May        wmay@cisco.com
 */
/*
 * sdp_decode.c
 *
 * decode SDP format from file into session description structures
 * defined in sdp.h
 *
 * October, 2000
 * Bill May (wmay@cisco.com)
 * Cisco Systems, Inc.
 */
#include "sdp.h"
#include "sdp_decode_private.h"

#define ADV_SPACE(a) {while (isspace(*(a)) && (*(a) != '\0'))(a)++;}

static const char *SPACES=" \t";

#define FREE_CHECK(a,b) if (a->b != NULL) { free(a->b); a->b = NULL;}

/*****************************************************************************
 * Memory free routines - frees memory associated with various structures
 *****************************************************************************/

static void free_bandwidth_desc (bandwidth_t *bptr)
{
  bandwidth_t *q;
  while (bptr != NULL) {
    q = bptr;
    bptr = q->next;
    FREE_CHECK(q, user_band);
    free(q);
  }
}

static void free_category_list (category_list_t **cptr)
{
  category_list_t *p;
  if (*cptr == NULL) return;
  
  while (*cptr != NULL) {
    p = *cptr;
    *cptr = p->next;
    free(p);
  }
}

static void free_connect_desc (connect_desc_t *cptr)
{
  FREE_CHECK(cptr, conn_type);
  FREE_CHECK(cptr, conn_addr);
}

/*
 * free_media_desc()
 * Frees all memory associated with a media descriptor(mptr)
 */
static void free_media_desc (media_desc_t *mptr)
{
  free_bandwidth_desc(mptr->media_bandwidth);
  mptr->media_bandwidth = NULL;
  free_connect_desc(&mptr->media_connect);
  sdp_free_format_list(&mptr->fmt);
  sdp_free_string_list(&mptr->unparsed_a_lines);
  FREE_CHECK(mptr, media);
  FREE_CHECK(mptr, media_desc);
  FREE_CHECK(mptr, proto);
  FREE_CHECK(mptr, sdplang);
  FREE_CHECK(mptr, lang);
  FREE_CHECK(mptr, orient_user_type);
  FREE_CHECK(mptr, control_string);
  FREE_CHECK(mptr, key.key);
  mptr->parent = NULL;
  free(mptr);
}

static void free_time_desc (session_time_desc_t *time)
{
  time_repeat_desc_t *rptr;
  
  if (time->next != NULL) {
    free_time_desc(time->next);
    time->next = NULL;
  }
  while (time->repeat != NULL) {
    rptr = time->repeat;
    time->repeat = rptr->next;
    free (rptr);
  }

  free(time);
}

/*
 * sdp_free_session_desc()
 * Inputs - sptr - pointer to session_description list to free
 */
void sdp_free_session_desc (session_desc_t *sptr)
{
  session_desc_t *p;
  media_desc_t *mptr, *q;

  p = sptr;
  while (p != NULL) {
    sptr = p;
    p = p->next;
    
    sptr->next = NULL;
    mptr = sptr->media;
    sptr->media = NULL;

    while (mptr != NULL) {
      q = mptr;
      mptr = q->next;
      free_media_desc(q);
    }

    FREE_CHECK(sptr, etag);
    FREE_CHECK(sptr, orig_username);
    FREE_CHECK(sptr, control_string);
    FREE_CHECK(sptr, create_addr_type);
    FREE_CHECK(sptr, create_addr);
    FREE_CHECK(sptr, session_name);
    FREE_CHECK(sptr, session_desc);
    FREE_CHECK(sptr, uri);
    FREE_CHECK(sptr, key.key);
    FREE_CHECK(sptr, keywds);
    FREE_CHECK(sptr, lang);
    FREE_CHECK(sptr, tool);
    FREE_CHECK(sptr, charset);
    FREE_CHECK(sptr, sdplang);
    FREE_CHECK(sptr, conf_type_user);

    if (sptr->time_desc != NULL) {
      free_time_desc(sptr->time_desc);
      sptr->time_desc = NULL;
    }

    free_bandwidth_desc(sptr->session_bandwidth);
    sptr->session_bandwidth = NULL;
    free_category_list(&sptr->category_list);
    free_connect_desc(&sptr->session_connect);
    sdp_free_string_list(&sptr->admin_phone);
    sdp_free_string_list(&sptr->admin_email);
    sdp_free_string_list(&sptr->unparsed_a_lines);
    
    while (sptr->time_adj_desc != NULL) {
      time_adj_desc_t *aptr;
      aptr = sptr->time_adj_desc;
      sptr->time_adj_desc = aptr->next;
      free(aptr);
    }
  
    free(sptr);
  }
}

/*****************************************************************************
 * Utility routines - string manipulation, etc
 *****************************************************************************/
/*
 * get_next_line will get the next line to process, and stick it in
 * lptr.
 *
 * Inputs:
 *    lptr - buffer to store into
 *    decode - pointer to where to get next line
 *    buflen - max length of buffer
 *
 * Outputs:
 *    TRUE - have a new line.
 *    FALSE - all done.
 */
static int get_next_line (char **polptr,
			  sdp_decode_info_t *decode,
			  uint32_t *buflen)
{
  char *fret;
  uint32_t len;
  uint32_t buflen_left;
  const char *cptr;

  if (decode->isMem) {
    cptr = decode->memptr;

    if (*cptr == '\0') return FALSE;

    while (*cptr != '\0' && *cptr != '\n' && *cptr != '\r') cptr++;

    len = cptr - decode->memptr;
    if (*buflen <= len + 1) {
      if (len > 65535) {
	sdp_debug(LOG_CRIT, "Max line length of 65535 exceeded %u", 
		  len);
	return (FALSE);
      }
      *polptr = realloc(*polptr, len + 1);
      *buflen = len + 1;
    }
    memcpy(*polptr, decode->memptr, len);
    (*polptr)[len] = '\0';
    decode->memptr += len;
    while (*decode->memptr == '\n' || *decode->memptr == '\r')
      decode->memptr++;
  } else {
    char *ptr;
    // File reads...
    if (decode->ifile == NULL)
      return FALSE;
    if (*buflen == 0) {
      *polptr = (char *)malloc(1024);
      *buflen = 1024;
    }

    // Read file until we hit the end, or a non-blank line read
    ptr = *polptr;
    buflen_left = *buflen;
    len = 0;

    while (1) {
      fret = fgets(ptr, buflen_left, decode->ifile);
      if (fret == NULL) {
	if (len > 0) {
	  sdp_debug(LOG_WARNING, "Unterminated last line");
	  (*polptr)[len] = '\0'; // make sure
	  return (TRUE);
	}
	return (FALSE);
      }

      len = strlen(ptr);
      if (ptr[len - 1] == '\n' || ptr[len - 1] == '\r') {
	// we have an end of line
	len--;
	while (len >= 0 &&
	       (ptr[len] == '\n' || ptr[len] == '\r')) {
	  ptr[len] = '\0';
	  len--;
	}
	return (TRUE);
      }
      
      // too long...
      buflen_left -= len;
      if (*buflen + 1024 > 65535) {
	sdp_debug(LOG_CRIT, "Max line length of 65535 exceeded %u", 
		  *buflen);
	return (FALSE);
      }
      *buflen += 1024;
      buflen_left += 1024;
      *polptr = realloc(*polptr, *buflen);
      ptr = *polptr + *buflen - buflen_left;
    }
  }

  return TRUE;
}

/*
 * strtou64()
 * Converts string to uint64_t number up to next space, with error checking.
 * Inputs:
 *    lptr - pointer to pointer to string.  *lptr will be modified
 *    num - return value
 * Outputs - TRUE - sucess, FALSE, failure
 */
static int strtou64 (char **lptr, uint64_t *num)
{
  char *sep;
  
  *num = 0;
  ADV_SPACE((*lptr));
  sep = strsep(lptr, SPACES);
  if (sep == NULL || *lptr == NULL) {
    return (FALSE);
  }
  *num = 0;
  while (*sep != '\0') {
    if (isdigit(*sep)) {
      *num *= 10;
      *num += *sep - '0';
      sep++;
    } else {
      return (FALSE);
    }
  }
  return (TRUE);
}

/*
 * str_to_time_offset()
 * converts typed-time field (number or [#d][#h][#m][#s])
 *
 * Inputs -
 *   str - \0 terminated string to translate
 *   retval - pointer to return value
 * Returns -
 *   TRUE - valid string processed;
 *   FALSE - invalid string
 */
static int str_to_time_offset (const char *str, uint32_t *retval)
{
  uint32_t value;
  uint32_t accum;
  char temp;
  
  value = 0;
  accum = 0;

  if (!isdigit(*str)) return (FALSE);
  
  while (*str != '\0') {
    if (isdigit(*str)) {
      accum *= 10;
      accum += (*str - '0');
    } else {
      temp = tolower(*str);
      if (temp == 'd') {
	value += accum * SEC_PER_DAY;
	accum = 0;
      } else if (temp == 'h') {
	value += accum * SEC_PER_HOUR;
	accum = 0;
      } else if (temp == 'm') {
	value += accum * SEC_PER_MINUTE;
	accum = 0;
      } else if (temp == 's') {
	value += accum;
	accum = 0;
      } else {
	sdp_debug(LOG_ERR, "Illegal character %c in time offset", temp);
	return (FALSE);
      }
    }
    str++;
  }
  value += accum;
  *retval = value;
  return (TRUE);
}

/*
 * time_adj_order_in_list()
 * order linked list by adj_time values.  We don't allow 2 items in the
 * list - "new" value might be free'd at end
 * Inputs:
 *   start - pointer to start of list
 *   new - pointer to new value
 * Returns:
 *   pointer to head of list - new value might be free'd.
 */
static time_adj_desc_t *time_adj_order_in_list (time_adj_desc_t *start,
						time_adj_desc_t *new)
{
  time_adj_desc_t *p, *q;
  if (start == NULL)
    return (new);

  p = start;
  q = NULL;
  while (p != NULL) {
    if (new->adj_time == p->adj_time) {
      sdp_debug(LOG_NOTICE, "Duplicate time %ld in adj description", p->adj_time);
      free(new);
      return (start);
    }
    if (new->adj_time < p->adj_time) {
      new->next = p;
      if (q == NULL) {
	return (new);
      } else {
	q->next = new;
	return (start);
      }
    }
    q = p;
    p = p->next;
  }
  q->next = new;
  return (start);
}


/*****************************************************************************
 * Line parsing routines
 *****************************************************************************/
/*
 * sdp_decode_parse_a_bool()
 * parses a boolean field.
 */
static int sdp_decode_parse_a_bool (int arg,
				    char *lptr,
				    session_desc_t *sptr,
				    media_desc_t *mptr)
{
  switch (arg) {
  case 0:
    if (mptr != NULL) mptr->recvonly = TRUE;
    else sptr->recvonly = TRUE;
    break;
  case 1:
    if (mptr != NULL) mptr->sendrecv = TRUE;
    else sptr->sendrecv = TRUE;
    break;
  case 2:
    if (mptr != NULL) mptr->sendonly = TRUE;
    else sptr->sendonly = TRUE;
    break;

  }
  return (0);
}

/*
 * sdp_decode_parse_a_rtpmap()
 * parses a=rtpmap:<fmt> <name>/<clockrate>[/<enc_param>]
 */
static int sdp_decode_parse_a_fmtp (int arg,
				    char *lptr,
				    session_desc_t *sptr,
				    media_desc_t *mptr)
{
  format_list_t *fptr;
  int len;
  
  if (mptr == NULL)
    return (-1);

  /*
   * See our format matches a value in the media's format list.
   */
  fptr = sdp_find_format_in_line(mptr->fmt,lptr) ;

  if (fptr == NULL) {
    sdp_debug(LOG_ALERT, "Can't find fmtp format %s in media format list", lptr);
    return (-1);
  }

  len = strlen(fptr->fmt);
  lptr += len;
  lptr++;
  ADV_SPACE(lptr);
  fptr->fmt_param = strdup(lptr);
  if (fptr->fmt_param == NULL) {
    return (-1);
  }
  return (0);
}

/*
 * sdp_decode_parse_a_rtpmap()
 * parses a=rtpmap:<fmt> <name>/<clockrate>[/<enc_param>]
 */
static int sdp_decode_parse_a_rtpmap (int arg,
				      char *lptr,
				      session_desc_t *sptr,
				      media_desc_t *mptr)
{
  char *enc, *slash, *temp;
  format_list_t *fptr;
  int len;
  uint32_t a, b;
  
  if (mptr == NULL)
    return (-1);

  /*
   * See our format matches a value in the media's format list.
   */
  fptr = sdp_find_format_in_line(mptr->fmt,lptr) ;

  if (fptr == NULL) {
    sdp_debug(LOG_ALERT, "Can't find rtpmap format %s in media list", lptr);
    return (-1);
  }

  len = strlen(fptr->fmt);
  /*
   * Matches entry left in fptr.  Decode rest of line
   */
  enc = lptr + len;
  ADV_SPACE(enc);

⌨️ 快捷键说明

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