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

📄 mpeg2_transport.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 2 页
字号:
			    buflen,
			    section_len,
			    mpeg2t_continuity_counter(buffer));
      return 0;
    }
    // pmapptr points to program number
  }

			    
  prog_num = ((pmapptr[0] << 8) | pmapptr[1]);
  if (prog_num != pmap_pid->program_number) {
    mpeg2t_message(LOG_ERR, 
		   "Prog Map error - program number doesn't match - pid %x orig %x from pak %x", 
		   pmap_pid->pid.pid, pmap_pid->program_number, prog_num);
    return 0;
  }
  pmap_pid->version_number = (pmapptr[2] >> 1) & 0x1f;

  pcr_pid = ((pmapptr[5] << 8) | pmapptr[6]) & 0x1fff;
  if (pcr_pid != 0x1fff) {
    mpeg2t_message(LOG_DEBUG, "Have PCR pid of %x", pcr_pid);
  }
  pmapptr += 7;
  section_len -= 7; // remove all the fixed fields to get the prog info len
  len = ((pmapptr[0] << 8) | pmapptr[1]) & 0xfff;
  pmapptr += 2;
  section_len -= 2;
  if (len != 0) {
    if (len > section_len) return 0;

    if (len == pmap_pid->prog_info_len) {
      // same length - do a compare
    } else {
    }
    pmapptr += len;
    section_len -= len;
  }
  section_len -= 4; // remove CRC
  len = 0;
  while (len < section_len) {
    stream_type = pmapptr[0];
    e_pid = ((pmapptr[1] << 8) | pmapptr[2]) & 0x1fff;
    es_len = ((pmapptr[3] << 8) | pmapptr[4]) & 0xfff;
    if (es_len + len > section_len) return 0;
    if (mpeg2t_lookup_pid(ptr, e_pid) == NULL) {
      mpeg2t_message(LOG_INFO, "Creating es pid %x", e_pid);
      create_es(ptr, e_pid, stream_type, &pmapptr[5], es_len);
    }
    // create_es
    len += 5 + es_len;
    pmapptr += 5 + es_len;
  }
  return 1;
}

static void clean_es_data (mpeg2t_es_t *es_pid) 
{
  switch (es_pid->stream_type) {
  case 1:
  case 2:
    // mpeg1 or mpeg2 video
    es_pid->work_state = 0;
    es_pid->header = 0;
    es_pid->work_loaded = 0;
    es_pid->have_seq_header = 0;
    break;
  case 3:
  case 4:
    // mpeg1/mpeg2 audio (mp3 codec
    if (es_pid->work != NULL ) {
      free(es_pid->work);
      es_pid->work = NULL;
    }
    es_pid->work_loaded = 0;
    es_pid->left = 0;
    break;
  case 0xf:
    // aac
    break;
  }
}  

void mpeg2t_malloc_es_work (mpeg2t_es_t *es_pid, uint32_t frame_len)
{
  uint8_t *frameptr;

  if (es_pid->work == NULL || es_pid->work->frame_len < frame_len) {
    if (es_pid->work != NULL) {
      free(es_pid->work);
      es_pid->work = NULL;
    }
    frameptr = (uint8_t *)malloc(sizeof(mpeg2t_frame_t) + frame_len);
    if (frameptr == NULL) return;
    es_pid->work = (mpeg2t_frame_t *)frameptr;
    es_pid->work->frame = frameptr + sizeof(mpeg2t_frame_t);
    es_pid->work->frame_len = frame_len;
  }
  es_pid->work->next_frame = NULL;
  es_pid->work->have_ps_ts = es_pid->have_ps_ts;
  es_pid->work->ps_ts = es_pid->ps_ts;
  es_pid->have_ps_ts = 0;
  es_pid->work_loaded = 0;
}

void mpeg2t_finished_es_work (mpeg2t_es_t *es_pid,
			      uint32_t frame_len)
{
  mpeg2t_frame_t *p;
  es_pid->work->frame_len = frame_len;
  if (es_pid->list == NULL) {
    es_pid->list = es_pid->work;
  } else {
    p = es_pid->list;
    while (p->next_frame != NULL) p = p->next_frame;
    p->next_frame = es_pid->work;
  }
  es_pid->work = NULL;
  es_pid->work_loaded = 0;
}

  
static int mpeg2t_process_es (mpeg2t_t *ptr, 
			      mpeg2t_pid_t *ifptr,
			      const uint8_t *buffer)
{
  uint32_t buflen;
  uint32_t pes_len;
  const uint8_t *esptr;
  mpeg2t_es_t *es_pid = (mpeg2t_es_t *)ifptr;
  int read_pes_options;
  uint8_t stream_id;
  uint32_t nextcc, pakcc;
  int ret;

  nextcc = ifptr->lastcc;
  nextcc = (nextcc + 1) & 0xf;
  pakcc = mpeg2t_continuity_counter(buffer);
  if (nextcc != pakcc) {
    mpeg2t_message(LOG_ERR, "cc error in PES %x should be %d is %d", 
	   ifptr->pid, nextcc, pakcc);
    clean_es_data(es_pid);
  }
  ifptr->lastcc = pakcc;

  buflen = 188;
  // process pas pointer
  esptr = mpeg2t_transport_payload_start(buffer, &buflen);
  if (esptr == NULL) return -1;

  
  if (mpeg2t_payload_unit_start_indicator(buffer) != 0) {
    // start of PES packet
    if ((esptr[0] != 0) ||
	(esptr[1] != 0) ||
	(esptr[2] != 1)) {
      mpeg2t_message(LOG_ERR, 
		     "Illegal start to PES packet - pid %x - %02x %02x %02x",
		     ifptr->pid, esptr[0], esptr[1], esptr[2]);
      return -1;
    }
    stream_id = es_pid->stream_id = esptr[3];
    pes_len = (esptr[4] << 8) | esptr[5];
    esptr += 6;
    buflen -= 6;
    
    read_pes_options = 0;
    // do we have header extensions
    switch ((stream_id & 0x70) >> 4) {
    default:
      if ((stream_id == 0xbd) ||
	    (stream_id >= 0xf3 && stream_id <= 0xf7) ||
	    (stream_id >= 0xf9 && stream_id <= 0xff)) {
	read_pes_options = 1;
	break;
      }
      // fall through
    case 4:
    case 5:
    case 6:
      if (esptr[2] <= buflen - 3) {
	// multiple PES for header
	read_pes_options = 1;
      } else {
	// don't have enough to read the header
      }
      break;
    }
      
    if (read_pes_options) {
      if (esptr[2] + 3 > buflen) {
	return 0;
      }
      //mpeg2t_read_pes_options(es_pid, esptr);
      if (((esptr[1] & 0xc0) == 0x80) ||
	  ((esptr[1] & 0xc0) == 0xc0)) {
	// read presentation timestamp
	uint64_t pts;
#if 1
	mpeg2t_message(LOG_DEBUG, "Stream %x %02x %02x %02x", 
	       stream_id, esptr[0], esptr[1], esptr[2]);
	mpeg2t_message(LOG_DEBUG, "PTS %02x %02x %02x %02x %02x", 
	       esptr[3], esptr[4], esptr[5], esptr[6], esptr[7]);
#endif
	if (((esptr[1] >> 6) & 0x3) !=
	    ((esptr[3] >> 4) & 0xf)) {
	  mpeg2t_message(LOG_ERR, "PID %x Timestamp flag value not same %x %x",
			 es_pid->pid.pid, esptr[1], esptr[2]);
	  return -1;
	}
	pts = ((esptr[3] >> 1) & 0x7);
	pts <<= 8;
	pts |= esptr[4];
	pts <<= 7;
	pts |= ((esptr[5] >> 1) & 0x7f);
	pts <<= 8;
	pts |= esptr[6];
	pts <<= 7;
	pts |= ((esptr[7] >> 1) & 0x7f);
	es_pid->have_ps_ts = 1;
	es_pid->ps_ts = pts;
      }
      buflen -= esptr[2] + 3;
      esptr += esptr[2] + 3;
    }
  // process esptr, buflen
    if (buflen == 0) {
      es_pid->have_ps_ts = 0;
      return 0;
    }
  } else {
    // 0 in Payload start - process frame at start
    read_pes_options = 0;
  }
  // have start of data is at esptr, buflen data
  ret = 0;
  switch (es_pid->stream_type) {
  case 1:
  case 2:
    // mpeg1 or mpeg2 video
    ret = process_mpeg2t_mpeg_video(es_pid, esptr, buflen);
    break;
  case 3:
  case 4:
    // mpeg1/mpeg2 audio (mp3 codec
    ret = process_mpeg2t_mpeg_audio(es_pid, esptr, buflen);
  break;
  case 0xf:
    // aac
    break;
  }
  es_pid->have_ps_ts = 0;
  return ret;
}
			    
      
mpeg2t_pid_t *mpeg2t_process_buffer (mpeg2t_t *ptr, 
				     const uint8_t *buffer, 
				     uint32_t buflen,
				     uint32_t *buflen_used)
{
  uint32_t offset;
  uint32_t remaining;
  uint32_t used;
  uint16_t rpid;
  mpeg2t_pid_t *pidptr;
  int ret;

  used = 0;
  remaining = buflen;
  while (used < buflen) {
    offset = mpeg2t_find_sync_byte(buffer, remaining);
    if (offset >= remaining) {
      *buflen_used = buflen;
      return NULL;
    }
    remaining -= offset;
    buffer += offset;
    used += offset;

    if (remaining < 188) {
      *buflen_used = used;
      return NULL;
    }

    // we have a complete buffer
    rpid = mpeg2t_pid(buffer);
#if 1
    mpeg2t_message(LOG_DEBUG, "Buffer- PID %x start %d cc %d",
		   rpid, mpeg2t_payload_unit_start_indicator(buffer),
		   mpeg2t_continuity_counter(buffer));
#endif
    if (rpid == 0x1fff) {
      // just skip
    } else {
      // look up pid in table
      pidptr = mpeg2t_lookup_pid(ptr, rpid);
      if (pidptr != NULL) {
	// okay - we've got a valid pid ptr
	switch (pidptr->pak_type) {
	case MPEG2T_PAS_PAK:
	  ret = mpeg2t_process_pas(ptr, buffer);
	  if (ret > 0) {
	    *buflen_used = used + 188;
	    return pidptr;
	  }
	  break;
	case MPEG2T_PROG_MAP_PAK:
	  ret = mpeg2t_process_pmap(ptr, pidptr, buffer);
	  if (ret > 0) {
	    *buflen_used = used + 188;
	    return pidptr;
	  }
	  break;
	case MPEG2T_ES_PAK:
	  if (mpeg2t_process_es(ptr, pidptr, buffer) > 0) {
	    *buflen_used = used + 188;
	    return pidptr;
	  }
	  break;
	}
      }
    }

    used += 188;
    buffer += 188;
    remaining -= 188;
  }
  *buflen_used = buflen;
  return NULL;
}
  
mpeg2t_t *create_mpeg2_transport (void)
{
  mpeg2t_t *ptr;

  ptr = MALLOC_STRUCTURE(mpeg2t_t);
  memset(ptr, 0, sizeof(ptr));
  ptr->pas.pid.pak_type = MPEG2T_PAS_PAK;
  ptr->pas.pid.next_pid = NULL;
  ptr->pas.pid.pid = 0;
  ptr->pas.pid.collect_pes = 1;
  return (ptr);
}

⌨️ 快捷键说明

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