·您当前的位置:首页 > 技术教程 > live555技术 >

[Live555]live555中处理mpeg4

时间:2015-06-16 13:44酷播
[Live555]live555中处理mpeg4

[Live555]live555中处理mpeg4

  1. void MPEG4VideoStreamDiscreteFramer 
  2. ::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes, 
  3.                      struct timeval presentationTime, 
  4.                      unsigned durationInMicroseconds) { 
  5.   // Check that the first 4 bytes are a system code: 
  6.   if (frameSize >= 4 && fTo[0] == 0 && fTo[1] == 0 && fTo[2] == 1) { 
  7.     fPictureEndMarker = True; // Assume that we have a complete 'picture' here 
  8.     unsigned i = 3
  9.  
  10.  
  11.     // 
  12.     //视觉对象序列,按照完整的MPEG4 Elemental Stream进行解析 
  13.     // 
  14.     if (fTo[i] == 0xB0) { // VISUAL_OBJECT_SEQUENCE_START_CODE 
  15.       // The next byte is the "profile_and_level_indication": 
  16.       if (frameSize >= 5) fProfileAndLevelIndication = fTo[4]; 
  17.  
  18.  
  19.       // The start of this frame - up to the first GROUP_VOP_START_CODE 
  20.       // or VOP_START_CODE - is stream configuration information.  Save this: 
  21.       for (i = 7; i < frameSize; ++i) { 
  22.     if ((fTo[i] == 0xB3 /*GROUP_VOP_START_CODE*/ || 
  23.          fTo[i] == 0xB6 /*VOP_START_CODE*/) 
  24.         && fTo[i-1] == 1 && fTo[i-2] == 0 && fTo[i-3] == 0) { 
  25.       break; // The configuration information ends here 
  26.     } 
  27.       } 
  28.       fNumConfigBytes = i < frameSize ? i-3 : frameSize; 
  29.       delete[] fConfigBytes; fConfigBytes = new unsigned char[fNumConfigBytes]; 
  30.       for (unsigned j = 0; j < fNumConfigBytes; ++j) fConfigBytes[j] = fTo[j]; 
  31.  
  32.  
  33.       // This information (should) also contain a VOL header, which we need 
  34.       // to analyze, to get "vop_time_increment_resolution" (which we need 
  35.       // - along with "vop_time_increment" - in order to generate accurate 
  36.       // presentation times for "B" frames). 
  37.       analyzeVOLHeader(); 
  38.     } 
  39.  
  40.  
  41.     if (i < frameSize) { 
  42.       u_int8_t nextCode = fTo[i]; 
  43.  
  44.  
  45.       // 
  46.       //VOP组 
  47.       // 
  48.       if (nextCode == 0xB3 /*GROUP_VOP_START_CODE*/) { 
  49.     // Skip to the following VOP_START_CODE (if any): 
  50.     for (i += 4; i < frameSize; ++i) { 
  51.       if (fTo[i] == 0xB6 /*VOP_START_CODE*/ 
  52.           && fTo[i-1] == 1 && fTo[i-2] == 0 && fTo[i-3] == 0) { 
  53.         nextCode = fTo[i]; 
  54.         break; 
  55.       } 
  56.     } 
  57.       } 
  58.  
  59.  
  60.       // 
  61.       //视觉对象平面 
  62.       // 
  63.       if (nextCode == 0xB6 /*VOP_START_CODE*/ && i+5 < frameSize) { 
  64.     ++i; 
  65.  
  66.  
  67.     // Get the "vop_coding_type" from the next byte: 
  68.     u_int8_t nextByte = fTo[i++]; 
  69.     u_int8_t vop_coding_type = nextByte>>6;   //VOP开始符后的2bit,表示帧类型I/P/B/S 
  70.  
  71.  
  72.     // Next, get the "modulo_time_base" by counting the '1' bits that 
  73.     // follow.  We look at the next 32-bits only. 
  74.     // This should be enough in most cases. 
  75.     u_int32_t next4Bytes 
  76.       = (fTo[i]<<24)|(fTo[i+1]<<16)|(fTo[i+2]<<8)|fTo[i+3]; 
  77.     i += 4; 
  78.     u_int32_t timeInfo = (nextByte<<(32-6))|(next4Bytes>>6); 
  79.     unsigned modulo_time_base = 0
  80.     u_int32_t mask = 0x80000000
  81.     while ((timeInfo&mask) != 0) { 
  82.       ++modulo_time_base; 
  83.       mask >>= 1; 
  84.     } 
  85.     mask >>= 2; 
  86.  
  87.  
  88.     // Then, get the "vop_time_increment". 
  89.     unsigned vop_time_increment = 0
  90.     // First, make sure we have enough bits left for this: 
  91.     if ((mask>>(fNumVTIRBits-1)) != 0) { 
  92.       for (unsigned i = 0; i < fNumVTIRBits; ++i) { 
  93.         vop_time_increment |= timeInfo&mask; 
  94.         mask >>= 1; 
  95.       } 
  96.       while (mask != 0) { 
  97.         vop_time_increment >>= 1; 
  98.         mask >>= 1; 
  99.       } 
  100.     } 
  101.  
  102.  
  103.     // 
  104.     //若是"B"frame, 需要修正时间时间戳 
  105.     // 
  106.     // If this is a "B" frame, then we have to tweak "presentationTime": 
  107.     if (vop_coding_type == 2/*B*/ 
  108.         && (fLastNonBFramePresentationTime.tv_usec > 0 || 
  109.         fLastNonBFramePresentationTime.tv_sec > 0)) { 
  110.       int timeIncrement 
  111.         = fLastNonBFrameVop_time_increment - vop_time_increment; 
  112.       if (timeIncrement<0) timeIncrement += vop_time_increment_resolution; 
  113.       unsigned const MILLION = 1000000
  114.       double usIncrement = vop_time_increment_resolution == 0 ? 0.0 
  115.         : ((double)timeIncrement*MILLION)/vop_time_increment_resolution; 
  116.       unsigned secondsToSubtract = (unsigned)(usIncrement/MILLION); 
  117.       unsigned uSecondsToSubtract = ((unsigned)usIncrement)%MILLION; 
  118.  
  119.  
  120.       presentationTime = fLastNonBFramePresentationTime
  121.       if ((unsigned)presentationTime.tv_usec < uSecondsToSubtract) { 
  122.         presentationTime.tv_usec += MILLION; 
  123.         if (presentationTime.tv_sec > 0) --presentationTime.tv_sec; 
  124.       } 
  125.       presentationTime.tv_usec -uSecondsToSubtract
  126.       if ((unsigned)presentationTime.tv_sec > secondsToSubtract) { 
  127.         presentationTime.tv_sec -secondsToSubtract
  128.       } else { 
  129.         presentationTimepresentationTime.tv_sec = presentationTime.tv_usec = 0
  130.       } 
  131.     } else { 
  132.       fLastNonBFramePresentationTime = presentationTime
  133.       fLastNonBFrameVop_time_increment = vop_time_increment
  134.     } 
  135.       } 
  136.     } 
  137.   } 
  138.  
  139.  
  140.   // Complete delivery to the client: 
  141.   fFrameSize = frameSize
  142.   fNumTruncatedBytes = numTruncatedBytes
  143.   fPresentationTime = presentationTime
  144.   fDurationInMicroseconds = durationInMicroseconds
  145.   afterGetting(this); 

 

热门文章推荐

请稍候...

保利威视云平台-轻松实现点播直播视频应用

酷播云数据统计分析跨平台播放器