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

📄 mpeg2_transport.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 2 页
字号:

#include "mpeg4ip.h"
#include "mpeg2_transport.h"
#include <assert.h>
#include "mpeg2t_private.h"
#define DEBUG 1
#ifdef DEBUG
#define CHECK_MP2T_HEADER assert(*pHdr == MPEG2T_SYNC_BYTE)
#else
#define CHECK_MP2T_HEADER 
#endif

uint32_t mpeg2t_find_sync_byte (const uint8_t *buffer, uint32_t buflen)
{
  uint32_t offset;

  offset = 0;

  while (offset < buflen) {
    if (buffer[offset] == MPEG2T_SYNC_BYTE) {
      return (offset);
    }
    offset++;
  }
  return (offset);
}

uint32_t mpeg2t_transport_error_indicator (const uint8_t *pHdr)
{

  CHECK_MP2T_HEADER;

  return ((pHdr[1] >> 7) & 0x1);
}

uint32_t mpeg2t_payload_unit_start_indicator (const uint8_t *pHdr)
{
  CHECK_MP2T_HEADER;

  return ((pHdr[1] >> 6) & 0x1);
}

uint16_t mpeg2t_pid (const uint8_t *pHdr)
{
  int pid;
  CHECK_MP2T_HEADER;

  pid = (pHdr[1] & 0x1f) << 8;
  pid |= pHdr[2];

  return (pid);
}

uint32_t mpeg2t_adaptation_control (const uint8_t *pHdr)
{
  CHECK_MP2T_HEADER;

  return ((pHdr[3] >> 4) & 0x3);
}

uint32_t mpeg2t_continuity_counter (const uint8_t *pHdr)
{
  CHECK_MP2T_HEADER;

  return (pHdr[3] & 0xf);
}

const uint8_t *mpeg2t_transport_payload_start (const uint8_t *pHdr,
					     uint32_t *payload_len)
{
  uint32_t adaption_control;
  CHECK_MP2T_HEADER;

  if (mpeg2t_transport_error_indicator(pHdr) != 0) {
    *payload_len = 0;
    return NULL;
  }

  adaption_control = mpeg2t_adaptation_control(pHdr);

  if (adaption_control == 1) {
    *payload_len = 184;
    return pHdr + 4;
  }
  if (adaption_control == 3) {
    if (pHdr[4] > 183) {
      *payload_len = 0;
      return NULL;
    }
    *payload_len = 183 - pHdr[4];
    return pHdr + 5 + pHdr[4];
  }

  *payload_len = 0;
  return NULL;
}

static void mpeg2t_start_join_pak (mpeg2t_pid_t *pidptr,
				   const uint8_t *bufstart,
				   uint32_t buflen,
				   uint32_t seqlen, 
				   uint32_t cc)
{
  if (seqlen == 0) {
    if (pidptr->data_len_max < buflen) {
      pidptr->data = (uint8_t *)realloc(pidptr->data, buflen + 4096);
      if (pidptr->data == NULL) {
	pidptr->data_len_max = 0;
	return;
      }
      pidptr->data_len_max = buflen + 4096;
    }
  } else if (seqlen > pidptr->data_len_max) {
    pidptr->data = (uint8_t *)realloc(pidptr->data, seqlen);
    if (pidptr->data == NULL) {
      pidptr->data_len_max = 0;
      return;
    }
    pidptr->data_len_max = seqlen;
  }
  pidptr->data_len = seqlen;
  pidptr->data_len_loaded = buflen;
  memcpy(pidptr->data, bufstart, buflen);
  pidptr->lastcc = cc;
}

static int mpeg2t_join_pak (mpeg2t_pid_t *pidptr,
			    const uint8_t *bufstart,
			    uint32_t buflen,
			    uint32_t cc)
{
  uint32_t nextcc;
  uint32_t remaining;
  if (pidptr->data_len_loaded == 0) {
    mpeg2t_message(LOG_WARNING, 
		   "Trying to add to unstarted packet - PID %x", 
		   pidptr->pid);
    return -1;
  }
  nextcc = (pidptr->lastcc + 1) & 0xf;
  if (nextcc != cc) {
    mpeg2t_message(LOG_ERR, "Illegal cc value %d - should be %d - PID %x", 
		   cc, nextcc, pidptr->pid);
    pidptr->data_len_loaded = 0;
    return -1;
  }
  pidptr->lastcc = cc;
  if (pidptr->data_len == 0) {
    remaining = pidptr->data_len_max - pidptr->data_len_loaded;
    if (remaining < buflen) {
      pidptr->data = (uint8_t *)realloc(pidptr->data, 
					pidptr->data_len_max + 4096);
      if (pidptr->data == NULL) {
	pidptr->data_len_max = 0;
	return -1;
      }
      pidptr->data_len_max = pidptr->data_len_max + 4096;
    }
  } else {
    remaining = pidptr->data_len - pidptr->data_len_loaded;

    buflen = buflen > remaining ? remaining : buflen;
  }
  memcpy(pidptr->data + pidptr->data_len_loaded,
	 bufstart, 
	 buflen);
  pidptr->data_len_loaded += buflen;
  if (pidptr->data_len == 0 || pidptr->data_len_loaded < pidptr->data_len) 
    return 0;
  // Indicate that next one starts from beginning
  pidptr->data_len_loaded = 0;
  return 1;
}

static mpeg2t_pid_t *mpeg2t_lookup_pid (mpeg2t_t *ptr,
					uint16_t pid)
{
  mpeg2t_pid_t *pidptr = &ptr->pas.pid;

  while (pidptr != NULL && pidptr->pid != pid) {
    pidptr = pidptr->next_pid;
  }
  return pidptr;
}

static void add_to_pidQ (mpeg2t_t *ptr, mpeg2t_pid_t *pidptr)
{
  mpeg2t_pid_t *p = &ptr->pas.pid;

  while (p->next_pid != NULL) {
    p = p->next_pid;
  }
  p->next_pid = pidptr;
}

static void create_pmap (mpeg2t_t *ptr, uint16_t prog_num, uint16_t pid)
{
  mpeg2t_pmap_t *pmap;

  mpeg2t_message(LOG_INFO, "Adding pmap prog_num %x pid %x", prog_num, pid);
  pmap = MALLOC_STRUCTURE(mpeg2t_pmap_t);
  if (pmap == NULL) return;
  memset(pmap, 0, sizeof(*pmap));
  pmap->pid.pak_type = MPEG2T_PROG_MAP_PAK;
  pmap->pid.pid = pid;
  pmap->program_number = prog_num;
  add_to_pidQ(ptr, &pmap->pid);
}

static void create_es (mpeg2t_t *ptr, 
		       uint16_t pid, 
		       uint8_t stream_type,
		       const uint8_t *es_data,
		       uint32_t es_info_len)
{
  mpeg2t_es_t *es;

  mpeg2t_message(LOG_INFO, 
		 "Adding ES PID %x stream type %d", pid, stream_type);
  es = MALLOC_STRUCTURE(mpeg2t_es_t);
  if (es == NULL) return;
  memset(es, 0, sizeof(*es));
  es->pid.pak_type = MPEG2T_ES_PAK;
  es->pid.pid = pid;
  es->stream_type = stream_type;
  if (es_info_len != 0) {
    es->es_data = (uint8_t *)malloc(es_info_len);
    if (es->es_data != NULL) {
      memcpy(es->es_data, es_data, es_info_len);
      es->es_info_len = es_info_len;
    }
  }
  es->work_max_size = 4096;
  add_to_pidQ(ptr, &es->pid);
}
  
static int mpeg2t_process_pas (mpeg2t_t *ptr, const uint8_t *buffer)
{
  uint32_t buflen;
  uint32_t section_len;
  uint32_t len;
  const uint8_t *mapptr;
  uint16_t prog_num, pid;
  const uint8_t *pasptr;
  int ret;

  buflen = 188;
  // process pas pointer
  pasptr = mpeg2t_transport_payload_start(buffer, &buflen);

  if (pasptr == NULL) return 0;

  if (mpeg2t_payload_unit_start_indicator(buffer) == 0) {
    ret = mpeg2t_join_pak(&ptr->pas.pid, 
			  pasptr,
			  buflen,
			  mpeg2t_continuity_counter(buffer));
    if (ret <= 0) return 0; // not done, or bad
    pasptr = ptr->pas.pid.data;
    section_len = ptr->pas.pid.data_len;
  } else {
    if (*pasptr + 1 > buflen) 
      return 0;
    buflen -= *pasptr + 1;
    pasptr += *pasptr + 1; // go through the pointer field
    
    if (*pasptr != 0 || (pasptr[1] & 0xc0) != 0x80) {
      mpeg2t_message(LOG_ERR, "PAS field not 0");
      return 0;
    }
    section_len = ((pasptr[1] << 8) | pasptr[2]) & 0x3ff; 
    // remove table_id, section length fields
    pasptr += 3;
    buflen -= 3;
    if (buflen < section_len) {
      mpeg2t_start_join_pak(&ptr->pas.pid,
			    pasptr, // start after section len
			    buflen,
			    section_len,
			    mpeg2t_continuity_counter(buffer));
      return 0;
    }
    // At this point, pasptr points to transport_stream_id
  }
  
  ptr->pas.transport_stream_id = ((pasptr[0] << 8 | pasptr[1]));
  ptr->pas.version_number = (pasptr[2] >> 1) & 0x1f;
  mapptr = &pasptr[5];
  section_len -= 5 + 4; // remove CRC and stuff before map list
  for (len = 0; len < section_len; len += 4, mapptr += 4) {
    prog_num = (mapptr[0] << 8) | mapptr[1];
    if (prog_num != 0) {
      pid = ((mapptr[2] << 8) | mapptr[3]) & 0x1fff;
      if (mpeg2t_lookup_pid(ptr, pid) == NULL) {
	create_pmap(ptr, prog_num, pid);
      }
    }
  }
  return 1;
}

static int mpeg2t_process_pmap (mpeg2t_t *ptr, 
				mpeg2t_pid_t *ifptr,
				const uint8_t *buffer)
{
  uint32_t buflen;
  uint32_t section_len;
  uint32_t len, es_len;
  uint16_t prog_num, pcr_pid;
  const uint8_t *pmapptr;
  mpeg2t_pmap_t *pmap_pid = (mpeg2t_pmap_t *)ifptr;
  int ret;
  uint8_t stream_type;
  uint16_t e_pid;

  buflen = 188;
  // process pas pointer
  pmapptr = mpeg2t_transport_payload_start(buffer, &buflen);
  if (pmapptr == NULL) return 0;

  if (mpeg2t_payload_unit_start_indicator(buffer) == 0) {
    ret = mpeg2t_join_pak(ifptr, 
			  pmapptr,
			  buflen,
			  mpeg2t_continuity_counter(buffer));
    if (ret <= 0) return 0;
    pmapptr = ifptr->data;
    section_len = ifptr->data_len;
  } else {
    if (*pmapptr + 1 > buflen) 
      return 0;
    buflen -= *pmapptr + 1;
    pmapptr += *pmapptr + 1; // go through the pointer field
    if (*pmapptr != 2 || (pmapptr[1] & 0xc0) != 0x80) {
      mpeg2t_message(LOG_ERR, "PMAP start field not 2");
      return 0;
    }
    section_len = ((pmapptr[1] << 8) | pmapptr[2]) & 0x3ff; 
    pmapptr += 3;
    buflen -= 3;

    if (buflen < section_len) {
      mpeg2t_start_join_pak(ifptr,
			    pmapptr,

⌨️ 快捷键说明

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