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

📄 h264.cpp

📁 完整的RTP RTSP代码库
💻 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. 2004.  All Rights Reserved. *  * Contributor(s):  *		Bill May wmay@cisco.com */#include "mpeg4ip.h"#include "mp4av_h264.h"#include "mpeg4ip_bitstream.h"//#define BOUND_VERBOSE 1static uint8_t exp_golomb_bits[256] = {8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };uint32_t h264_ue (CBitstream *bs){  uint32_t bits, read;  int bits_left;  uint8_t coded;  bool done = false;  uint32_t temp;  bits = 0;  // we want to read 8 bits at a time - if we don't have 8 bits,   // read what's left, and shift.  The exp_golomb_bits calc remains the  // same.  while (done == false) {    bits_left = bs->bits_remain();    if (bits_left < 8) {      read = bs->PeekBits(bits_left) << (8 - bits_left);      done = true;    } else {      read = bs->PeekBits(8);      if (read == 0) {	(void)bs->GetBits(8);	bits += 8;      } else {	done = true;      }    }  }  coded = exp_golomb_bits[read];  temp = bs->GetBits(coded);  bits += coded;  //  printf("ue - bits %d\n", bits);  return bs->GetBits(bits + 1) - 1;}int32_t h264_se (CBitstream *bs) {  uint32_t ret;  ret = h264_ue(bs);  if ((ret & 0x1) == 0) {    ret >>= 1;    int32_t temp = 0 - ret;    return temp;  }   return (ret + 1) >> 1;}static void h264_decode_annexb( uint8_t *dst, int *dstlen,                                const uint8_t *src, const int srclen ){  uint8_t *dst_sav = dst;  const uint8_t *end = &src[srclen];  while (src < end)  {    if (src < end - 3 && src[0] == 0x00 && src[1] == 0x00 &&        src[2] == 0x03)    {      *dst++ = 0x00;      *dst++ = 0x00;      src += 3;      continue;    }    *dst++ = *src++;  }  *dstlen = dst - dst_sav;}extern "C" bool h264_is_start_code (const uint8_t *pBuf) {  if (pBuf[0] == 0 &&       pBuf[1] == 0 &&       ((pBuf[2] == 1) ||       ((pBuf[2] == 0) && pBuf[3] == 1))) {    return true;  }  return false;}extern "C" uint32_t h264_find_next_start_code (const uint8_t *pBuf, 					       uint32_t bufLen){  uint32_t val, temp;  uint32_t offset;  offset = 0;  if (pBuf[0] == 0 &&       pBuf[1] == 0 &&       ((pBuf[2] == 1) ||       ((pBuf[2] == 0) && pBuf[3] == 1))) {    pBuf += 3;    offset = 3;  }  val = 0xffffffff;  while (offset < bufLen - 3) {    val <<= 8;    temp = val & 0xff000000;    val &= 0x00ffffff;    val |= *pBuf++;    offset++;    if (val == H264_START_CODE) {      if (temp == 0) return offset - 4;      return offset - 3;    }  }  return 0;}extern "C" uint8_t h264_nal_unit_type (const uint8_t *buffer){  uint32_t offset;  if (buffer[2] == 1) offset = 3;  else offset = 4;  return buffer[offset] & 0x1f;}extern "C" int h264_nal_unit_type_is_slice (const uint8_t type){  if (type >= H264_NAL_TYPE_NON_IDR_SLICE &&       type <= H264_NAL_TYPE_IDR_SLICE) {    return true;  }  return false;}/* * determine if the slice we decoded is a sync point */extern "C" bool h264_slice_is_idr (h264_decode_t *dec) {  if (dec->nal_unit_type != H264_NAL_TYPE_IDR_SLICE)    return false;  if (H264_TYPE_IS_I(dec->slice_type)) return true;  if (H264_TYPE_IS_SI(dec->slice_type)) return true;  return false;}extern "C" uint8_t h264_nal_ref_idc (const uint8_t *buffer){  uint32_t offset;  if (buffer[2] == 1) offset = 3;  else offset = 4;  return (buffer[offset] >> 5) & 0x3;}static void scaling_list (uint sizeOfScalingList, CBitstream *bs){  uint lastScale = 8, nextScale = 8;  uint j;  for (j = 0; j < sizeOfScalingList; j++) {    if (nextScale != 0) {      int deltaScale = h264_se(bs);      nextScale = (lastScale + deltaScale + 256) % 256;    }    if (nextScale == 0) {      lastScale = lastScale;    } else {      lastScale = nextScale;    }  }}int h264_read_seq_info (const uint8_t *buffer, 			uint32_t buflen, 			h264_decode_t *dec){  CBitstream bs;  uint32_t header;  uint8_t tmp[2048]; /* Should be enough for all SPS (we have at worst 13 bytes and 496 se/ue in frext) */  int tmp_len;  uint32_t dummy;  if (buffer[2] == 1) header = 4;  else header = 5;  h264_decode_annexb( tmp, &tmp_len, buffer + header, MIN(buflen-header,2048) );  bs.init(tmp, tmp_len * 8);  //bs.set_verbose(true);  try {    dec->profile = bs.GetBits(8);    dummy = bs.GetBits(1 + 1 + 1 + 1 + 4);    dec->level = bs.GetBits(8);    (void)h264_ue(&bs); // seq_parameter_set_id    if (dec->profile == 100 || dec->profile == 110 ||	dec->profile == 122 || dec->profile == 144) {      dec->chroma_format_idc = h264_ue(&bs);      if (dec->chroma_format_idc == 3) {	dec->residual_colour_transform_flag = bs.GetBits(1);      }      dec->bit_depth_luma_minus8 = h264_ue(&bs);      dec->bit_depth_chroma_minus8 = h264_ue(&bs);      dec->qpprime_y_zero_transform_bypass_flag = bs.GetBits(1);      dec->seq_scaling_matrix_present_flag = bs.GetBits(1);      if (dec->seq_scaling_matrix_present_flag) {	for (uint ix = 0; ix < 8; ix++) {	  if (bs.GetBits(1)) {	    scaling_list(ix < 6 ? 16 : 64, &bs);	  }	}      }    }    dec->log2_max_frame_num_minus4 = h264_ue(&bs);    dec->pic_order_cnt_type = h264_ue(&bs);    if (dec->pic_order_cnt_type == 0) {      dec->log2_max_pic_order_cnt_lsb_minus4 = h264_ue(&bs);    } else if (dec->pic_order_cnt_type == 1) {      dec->delta_pic_order_always_zero_flag = bs.GetBits(1);      dec->offset_for_non_ref_pic = h264_se(&bs); // offset_for_non_ref_pic      dec->offset_for_top_to_bottom_field = h264_se(&bs); // offset_for_top_to_bottom_field      dec->pic_order_cnt_cycle_length = h264_ue(&bs); // poc_cycle_length      for (uint32_t ix = 0; ix < dec->pic_order_cnt_cycle_length; ix++) {        dec->offset_for_ref_frame[MIN(ix,255)] = h264_se(&bs); // offset for ref fram -      }    }    dummy = h264_ue(&bs); // num_ref_frames    dummy = bs.GetBits(1); // gaps_in_frame_num_value_allowed_flag    uint32_t PicWidthInMbs = h264_ue(&bs) + 1;    dec->pic_width = PicWidthInMbs * 16;    uint32_t PicHeightInMapUnits = h264_ue(&bs) + 1;    dec->frame_mbs_only_flag = bs.GetBits(1);    dec->pic_height =       (2 - dec->frame_mbs_only_flag) * PicHeightInMapUnits * 16;#if 0    if (!dec->frame_mbs_only_flag) {      printf("    mb_adaptive_frame_field_flag: %u\n", bs->GetBits(1));    }    printf("   direct_8x8_inference_flag: %u\n", bs->GetBits(1));    temp = bs->GetBits(1);    printf("   frame_cropping_flag: %u\n", temp);    if (temp) {      printf("     frame_crop_left_offset: %u\n", h264_ue(bs));      printf("     frame_crop_right_offset: %u\n", h264_ue(bs));      printf("     frame_crop_top_offset: %u\n", h264_ue(bs));      printf("     frame_crop_bottom_offset: %u\n", h264_ue(bs));    }    temp = bs->GetBits(1);    printf("   vui_parameters_present_flag: %u\n", temp);    if (temp) {      h264_vui_parameters(bs);    }#endif  } catch (...) {    return -1;  }  return 0;}extern "C" int h264_find_slice_type (const uint8_t *buffer, 				     uint32_t buflen,				     uint8_t *slice_type, 				     bool noheader){  uint32_t header;  uint32_t dummy;  if (noheader) header = 1;  else {    if (buffer[2] == 1) header = 4;    else header = 5;  }  CBitstream bs;  bs.init(buffer + header, (buflen - header) * 8);  try {    dummy = h264_ue(&bs); // first_mb_in_slice    *slice_type = h264_ue(&bs); // slice type  } catch (...) {    return -1;  }  return 0;}int h264_read_slice_info (const uint8_t *buffer, 			  uint32_t buflen, 			  h264_decode_t *dec){  uint32_t header;  uint8_t tmp[512]; /* Enough for the begining of the slice header */  int tmp_len;  uint32_t temp;  if (buffer[2] == 1) header = 4;  else header = 5;  CBitstream bs;  h264_decode_annexb( tmp, &tmp_len, buffer + header, MIN(buflen-header,512) );  bs.init(tmp, tmp_len * 8);  try {    dec->field_pic_flag = 0;    dec->bottom_field_flag = 0;    dec->delta_pic_order_cnt[0] = 0;    dec->delta_pic_order_cnt[1] = 0;    temp = h264_ue(&bs); // first_mb_in_slice    dec->slice_type = h264_ue(&bs); // slice type    temp = h264_ue(&bs); // pic_parameter_set    dec->frame_num = bs.GetBits(dec->log2_max_frame_num_minus4 + 4);    if (!dec->frame_mbs_only_flag) {      dec->field_pic_flag = bs.GetBits(1);      if (dec->field_pic_flag) {	dec->bottom_field_flag = bs.GetBits(1);      }    }    if (dec->nal_unit_type == H264_NAL_TYPE_IDR_SLICE) {      dec->idr_pic_id = h264_ue(&bs);    }    switch (dec->pic_order_cnt_type) {    case 0:      dec->pic_order_cnt_lsb = bs.GetBits(dec->log2_max_pic_order_cnt_lsb_minus4 + 4);      if (dec->pic_order_present_flag && !dec->field_pic_flag) {	dec->delta_pic_order_cnt_bottom = h264_se(&bs);      }      break;    case 1:      if (!dec->delta_pic_order_always_zero_flag) {	dec->delta_pic_order_cnt[0] = h264_se(&bs);      }      if (dec->pic_order_present_flag && !dec->field_pic_flag) {

⌨️ 快捷键说明

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