예제 #1
0
char const* H264VideoRTPSink::auxSDPLine() {

  liveLogInfo(" H264VideoRTPSink::auxSDPLine \n");
  
  // Generate a new "a=fmtp:" line each time, using our SPS and PPS (if we have them),
  // otherwise parameters from our framer source (in case they've changed since the last time that
  // we were called):
  H264or5VideoStreamFramer* framerSource = NULL;
  u_int8_t* vpsDummy = NULL; unsigned vpsDummySize = 0;
  u_int8_t* sps = fSPS; unsigned spsSize = fSPSSize;
  u_int8_t* pps = fPPS; unsigned ppsSize = fPPSSize;
  if (sps == NULL || pps == NULL) {
    // We need to get SPS and PPS from our framer source:
    if (fOurFragmenter == NULL) return NULL; // we don't yet have a fragmenter (and therefore not a source)
    framerSource = (H264or5VideoStreamFramer*)(fOurFragmenter->inputSource());
    if (framerSource == NULL) return NULL; // we don't yet have a source

    framerSource->getVPSandSPSandPPS(vpsDummy, vpsDummySize, sps, spsSize, pps, ppsSize);
    if (sps == NULL || pps == NULL) return NULL; // our source isn't ready
  }

  // Set up the "a=fmtp:" SDP line for this stream:
  u_int8_t* spsWEB = new u_int8_t[spsSize]; // "WEB" means "Without Emulation Bytes"
  unsigned spsWEBSize = removeH264or5EmulationBytes(spsWEB, spsSize, sps, spsSize);
  if (spsWEBSize < 4) { // Bad SPS size => assume our source isn't ready
    delete[] spsWEB;
    return NULL;
  }
  u_int32_t profileLevelId = (spsWEB[1]<<16) | (spsWEB[2]<<8) | spsWEB[3];
  delete[] spsWEB;

  char* sps_base64 = base64Encode((char*)sps, spsSize);
  char* pps_base64 = base64Encode((char*)pps, ppsSize);

  char const* fmtpFmt =
    "a=fmtp:%d packetization-mode=1"
    ";profile-level-id=%06X"
    ";sprop-parameter-sets=%s,%s\r\n";
  unsigned fmtpFmtSize = strlen(fmtpFmt)
    + 3 /* max char len */
    + 6 /* 3 bytes in hex */
    + strlen(sps_base64) + strlen(pps_base64);
  char* fmtp = new char[fmtpFmtSize];
  sprintf(fmtp, fmtpFmt,
          rtpPayloadType(),
	  profileLevelId,
          sps_base64, pps_base64);

  delete[] sps_base64;
  delete[] pps_base64;

  delete[] fFmtpSDPLine; fFmtpSDPLine = fmtp;
  return fFmtpSDPLine;
}
예제 #2
0
void H264or5VideoRTPSink::doSpecialFrameHandling(unsigned /*fragmentationOffset*/,
						 unsigned char* /*frameStart*/,
						 unsigned /*numBytesInFrame*/,
						 struct timeval framePresentationTime,
						 unsigned /*numRemainingBytes*/) {
  // Set the RTP 'M' (marker) bit iff
  // 1/ The most recently delivered fragment was the end of (or the only fragment of) an NAL unit, and
  // 2/ This NAL unit was the last NAL unit of an 'access unit' (i.e. video frame).
  if (fOurFragmenter != NULL) {
    H264or5VideoStreamFramer* framerSource
      = (H264or5VideoStreamFramer*)(fOurFragmenter->inputSource());
    // This relies on our fragmenter's source being a "H264or5VideoStreamFramer".
    if (((H264or5Fragmenter*)fOurFragmenter)->lastFragmentCompletedNALUnit()
	&& framerSource != NULL && framerSource->pictureEndMarker()) {
      setMarkerBit();
      framerSource->pictureEndMarker() = False;
    }
  }

  setTimestamp(framePresentationTime);
}
예제 #3
0
char const* H265VideoRTPSink::auxSDPLine() {
  // Generate a new "a=fmtp:" line each time, using our VPS, SPS and PPS (if we have them),
  // otherwise parameters from our framer source (in case they've changed since the last time that
  // we were called):
  H264or5VideoStreamFramer* framerSource = NULL;
  u_int8_t* vps = fVPS; unsigned vpsSize = fVPSSize;
  u_int8_t* sps = fSPS; unsigned spsSize = fSPSSize;
  u_int8_t* pps = fPPS; unsigned ppsSize = fPPSSize;
  if (vps == NULL || sps == NULL || pps == NULL) {
    // We need to get VPS, SPS and PPS from our framer source:
    if (fOurFragmenter == NULL) return NULL; // we don't yet have a fragmenter (and therefore not a source)
    framerSource = (H264or5VideoStreamFramer*)(fOurFragmenter->inputSource());
    if (framerSource == NULL) return NULL; // we don't yet have a source

    framerSource->getVPSandSPSandPPS(vps, vpsSize, sps, spsSize, pps, ppsSize);
    if (vps == NULL || sps == NULL || pps == NULL) {
      return NULL; // our source isn't ready
    }
  }

  // Set up the "a=fmtp:" SDP line for this stream.
  u_int8_t* vpsWEB = new u_int8_t[vpsSize]; // "WEB" means "Without Emulation Bytes"
  unsigned vpsWEBSize = removeH264or5EmulationBytes(vpsWEB, vpsSize, vps, vpsSize);
  if (vpsWEBSize < 6/*'profile_tier_level' offset*/ + 12/*num 'profile_tier_level' bytes*/) {
    // Bad VPS size => assume our source isn't ready
    delete[] vpsWEB;
    return NULL;
  }
  u_int8_t const* profileTierLevelHeaderBytes = &vpsWEB[6];
  unsigned profileSpace  = profileTierLevelHeaderBytes[0]>>6; // general_profile_space
  unsigned profileId = profileTierLevelHeaderBytes[0]&0x1F; // general_profile_idc
  unsigned tierFlag = (profileTierLevelHeaderBytes[0]>>5)&0x1; // general_tier_flag
  unsigned levelId = profileTierLevelHeaderBytes[11]; // general_level_idc
  u_int8_t const* interop_constraints = &profileTierLevelHeaderBytes[5];
  char interopConstraintsStr[100];
  sprintf(interopConstraintsStr, "%02X%02X%02X%02X%02X%02X", 
	  interop_constraints[0], interop_constraints[1], interop_constraints[2],
	  interop_constraints[3], interop_constraints[4], interop_constraints[5]);
  delete[] vpsWEB;

  char* sprop_vps = base64Encode((char*)vps, vpsSize);
  char* sprop_sps = base64Encode((char*)sps, spsSize);
  char* sprop_pps = base64Encode((char*)pps, ppsSize);

  char const* fmtpFmt =
    "a=fmtp:%d profile-space=%u"
    ";profile-id=%u"
    ";tier-flag=%u"
    ";level-id=%u"
    ";interop-constraints=%s"
    ";sprop-vps=%s"
    ";sprop-sps=%s"
    ";sprop-pps=%s\r\n";
  unsigned fmtpFmtSize = strlen(fmtpFmt)
    + 3 /* max num chars: rtpPayloadType */ + 20 /* max num chars: profile_space */
    + 20 /* max num chars: profile_id */
    + 20 /* max num chars: tier_flag */
    + 20 /* max num chars: level_id */
    + strlen(interopConstraintsStr)
    + strlen(sprop_vps)
    + strlen(sprop_sps)
    + strlen(sprop_pps);
  char* fmtp = new char[fmtpFmtSize];
  sprintf(fmtp, fmtpFmt,
          rtpPayloadType(), profileSpace,
	  profileId,
	  tierFlag,
	  levelId,
	  interopConstraintsStr,
	  sprop_vps,
	  sprop_sps,
	  sprop_pps);

  delete[] sprop_vps;
  delete[] sprop_sps;
  delete[] sprop_pps;

  delete[] fFmtpSDPLine; fFmtpSDPLine = fmtp;
  return fFmtpSDPLine;
}