Ejemplo n.º 1
0
extern "C" bool MP4AV_Rfc2429Hinter (MP4FileHandle file,
				     MP4TrackId mediaTrackId,
				     uint16_t maxPayloadSize)
{
  uint32_t numSamples, maxSampleSize;
  MP4TrackId hid;
  MP4Duration duration;

  numSamples = MP4GetTrackNumberOfSamples(file, mediaTrackId);
  if (numSamples == 0) {
    return false;
  }
  maxSampleSize = MP4GetTrackMaxSampleSize(file, mediaTrackId);
  u_int8_t* pSampleBuffer = (u_int8_t*)malloc(maxSampleSize);
  if (pSampleBuffer == NULL) {
    return false;
  }

  hid = MP4AddHintTrack(file, mediaTrackId);
  if (hid == MP4_INVALID_TRACK_ID) {
    return false;
  }

  uint8_t payloadNumber = MP4_SET_DYNAMIC_PAYLOAD;
  MP4SetHintTrackRtpPayload(file,
                            hid,
                            "H263-2000",
                            &payloadNumber,
                            0,
                            NULL,
                            true,
                            false);

  // strictly speaking, this is not required for H.263 - it's a quicktime
  // thing.
  u_int16_t videoWidth = MP4GetTrackVideoWidth(file, mediaTrackId);
  u_int16_t videoHeight = MP4GetTrackVideoHeight(file, mediaTrackId);
  
  char sdpString[80];
  sprintf(sdpString, "a=cliprect:0,0,%d,%d\015\012", videoHeight, videoWidth);
  
  MP4AppendHintTrackSdp(file, 
 			hid,
 			sdpString);

  for (uint32_t sid = 1; sid <= numSamples; sid++) {

    duration = MP4GetSampleDuration(file, mediaTrackId, sid);

    MP4AddRtpVideoHint(file, hid, false, 0);

    u_int32_t sampleSize = maxSampleSize;
    MP4Timestamp startTime;
    MP4Duration duration;
    MP4Duration renderingOffset;
    bool isSyncSample;

    bool rc = MP4ReadSample(file, mediaTrackId, sid,
                            &pSampleBuffer, &sampleSize,
                            &startTime, &duration,
                            &renderingOffset, &isSyncSample);

    if (!rc) {
      MP4DeleteTrack(file, hid);
      free(pSampleBuffer);
      return false;
    }

    // need to skip the first 2 bytes of the packet - it is the
    //start code
    uint16_t payload_head = htons(0x400);
    uint32_t offset = sizeof(payload_head);
    uint32_t remaining = sampleSize - sizeof(payload_head);
    while (remaining) {
      bool last_pak = false;
      uint32_t len;

      if (remaining + 2 <= maxPayloadSize) {
        len = remaining;
        last_pak = true;
      } else {
        len = maxPayloadSize - 2;
      }
      MP4AddRtpPacket(file, hid, last_pak);

      MP4AddRtpImmediateData(file, hid,
                            (u_int8_t*)&payload_head, sizeof(payload_head));
      payload_head = 0;
      MP4AddRtpSampleData(file, hid, sid,
                          offset, len);
      offset += len;
      remaining -= len;
    }
    MP4WriteRtpHint(file, hid, duration, true);
  }

  free(pSampleBuffer);

  return true;
}
Ejemplo n.º 2
0
 extern "C" MP4TrackId MP4AV_AVSM_HintTrackCreate (MP4FileHandle mp4File,
						  MP4TrackId mediaTrackId)
{
  MP4TrackId hintTrackId =
    MP4AddHintTrack(mp4File, mediaTrackId);						//添加hint相关的原子mdia.minf.hmhd;mdia.minf.stbl.stsd.rtp
																//mdia.minf.stbl.stsd.rtp .tims.timeScale;tref.hint;udta.hnti.sdp
																//udta.hinf
 
  
  if (hintTrackId == MP4_INVALID_TRACK_ID) {					
    return MP4_INVALID_TRACK_ID;
  }

  u_int8_t payloadNumber = MP4_SET_DYNAMIC_PAYLOAD;

  // don't include mpeg4-esid
  MP4SetHintTrackRtpPayload(mp4File, hintTrackId, 
			    "AVSM", &payloadNumber, 0,						//改变名称“H264”
			    NULL, true, false);
				
  // get the mpeg4 video configuration 
  u_int8_t **pSeq, **pPict ;
  u_int32_t *pSeqSize, *pPictSize;								//参数改变
  char *base64;
  uint32_t profile_level;
  char *sprop = NULL;
  uint32_t ix = 0;

 MP4GetTrackAVSMSeqPictHeaders(mp4File,
				mediaTrackId,
				&pSeq,
				&pSeqSize,										//**获得序列头和图像头相关参数pSeq,pSeqSize,pPict,pPictSize
				&pPict,
				&pPictSize);
				      
  if (pSeqSize && pSeqSize[0] != 0) {								//添加seq参数集
    // we have valid sequence and picture headers
    uint8_t *p = pSeq[0];
    if (*p == 0 && p[1] == 0 && 
	(p[2] == 1 || (p[2] == 0 && p[3] == 0))) {
      if (p[2] == 0) p += 4;
      else p += 3;
    }
    profile_level = p[1] << 8 | p[2];
    while (pSeqSize[ix] != 0) {
      base64 = MP4BinaryToBase64(pSeq[ix], pSeqSize[ix]);
      if (sprop == NULL) {
	sprop = strdup(base64);
      } else {
	sprop = (char *)realloc(sprop, strlen(sprop) + strlen(base64) + 1 + 1);
	strcat(sprop, ",");
	strcat(sprop, base64);
      }
      free(base64);
      free(pSeq[ix]);
      ix++;
    }
    free(pSeq);
    free(pSeqSize);

    ix = 0;
    while (pPictSize[ix] != 0) {									//添加picture参数集
      base64 = MP4BinaryToBase64(pPict[ix], pPictSize[ix]);
      sprop = (char *)realloc(sprop, strlen(sprop) + strlen(base64) + 1 + 1);
      strcat(sprop, ",");
      strcat(sprop, base64);
      free(base64);
      free(pPict[ix]);
      ix++;
    }																
    free(pPict);
    free(pPictSize);

    // create the appropriate SDP attribute *
    char* sdpBuf = (char*)malloc(strlen(sprop) + 128);				//sdp
	
	u_int16_t svideoWidth = MP4GetTrackVideoWidth(mp4File, mediaTrackId);		
	u_int16_t svideoHeight = MP4GetTrackVideoHeight(mp4File, mediaTrackId);	//********添加********
  
	  
    sprintf(sdpBuf,
		"a=cliprect:0,0,%d,%d\015\012"
	    "a=fmtp:%u profile-level-id=%04x; sprop-parameter-sets=%s; packetization-mode=1\015\012",
	    svideoWidth,
		svideoHeight,
		payloadNumber,
	    profile_level,
	    sprop); 
	  
    /* add this to the track's sdp */
    MP4AppendHintTrackSdp(mp4File, hintTrackId, sdpBuf);
	  
    free(sprop);
    free(sdpBuf);
  }
  return hintTrackId;
}
Ejemplo n.º 3
0
extern "C" bool MP4AV_RfcIsmaHinter(
	MP4FileHandle mp4File, 
	MP4TrackId mediaTrackId, 
	bool interleave,
	u_int16_t maxPayloadSize)
{
	// gather information, and check for validity

	u_int32_t numSamples =
		MP4GetTrackNumberOfSamples(mp4File, mediaTrackId);

	if (numSamples == 0) {
		return false;
	}

	u_int32_t timeScale =
		MP4GetTrackTimeScale(mp4File, mediaTrackId);

	if (timeScale == 0) {
		return false;
	}

	u_int8_t audioType =
		MP4GetTrackEsdsObjectTypeId(mp4File, mediaTrackId);

	if (audioType != MP4_MPEG4_AUDIO_TYPE
	  && !MP4_IS_AAC_AUDIO_TYPE(audioType)) {
		return false;
	}

	u_int8_t mpeg4AudioType =
		MP4GetTrackAudioMpeg4Type(mp4File, mediaTrackId);

	if (audioType == MP4_MPEG4_AUDIO_TYPE) {
		// check that track contains either MPEG-4 AAC or CELP
		if (!MP4_IS_MPEG4_AAC_AUDIO_TYPE(mpeg4AudioType) 
		  && mpeg4AudioType != MP4_MPEG4_CELP_AUDIO_TYPE) {
			return false;
		}
	}

	MP4Duration sampleDuration = 
		MP4AV_GetAudioSampleDuration(mp4File, mediaTrackId);

	if (sampleDuration == MP4_INVALID_DURATION) {
		return false;
	}

	/* get the ES configuration */
	u_int8_t* pConfig = NULL;
	u_int32_t configSize;
	uint8_t channels;

	if (MP4GetTrackESConfiguration(mp4File, mediaTrackId, 
				       &pConfig, &configSize) == false)
	  return false;

	if (!pConfig) {
		return false;
	}
     
	channels = MP4AV_AacConfigGetChannels(pConfig);

	/* convert ES Config into ASCII form */
	char* sConfig = 
		MP4BinaryToBase16(pConfig, configSize);

	free(pConfig);

	if (!sConfig) {
		return false;
	}

	/* create the appropriate SDP attribute */
	uint sdpBufLen = strlen(sConfig) + 256;
	char* sdpBuf = 
	  (char*)malloc(sdpBufLen);

	if (!sdpBuf) {
		free(sConfig);
		return false;
	}


	// now add the hint track
	MP4TrackId hintTrackId =
		MP4AddHintTrack(mp4File, mediaTrackId);

	if (hintTrackId == MP4_INVALID_TRACK_ID) {
		free(sConfig);
		free(sdpBuf);
		return false;
	}

	u_int8_t payloadNumber = MP4_SET_DYNAMIC_PAYLOAD;
	char buffer[10];
	if (channels != 1) {
	  snprintf(buffer, sizeof(buffer), "%u", channels);
	}
	if (MP4SetHintTrackRtpPayload(mp4File, hintTrackId, 
				      "mpeg4-generic", &payloadNumber, 0,
				      channels != 1 ? buffer : NULL) == false) {
	  MP4DeleteTrack(mp4File, hintTrackId);
	  free(sConfig);
	  free(sdpBuf);
	  return false;
	}

	MP4Duration maxLatency;
	bool OneByteHeader = false;
	if (mpeg4AudioType == MP4_MPEG4_CELP_AUDIO_TYPE) {
	  snprintf(sdpBuf, sdpBufLen,
			"a=fmtp:%u "
			"streamtype=5; profile-level-id=15; mode=CELP-vbr; config=%s; "
			"SizeLength=6; IndexLength=2; IndexDeltaLength=2; Profile=0;"
			"\015\012",
				payloadNumber,
				sConfig); 

		// 200 ms max latency for ISMA profile 1
		maxLatency = timeScale / 5;
		OneByteHeader = true;
	} else { // AAC
	  snprintf(sdpBuf, sdpBufLen,
			"a=fmtp:%u "
			"streamtype=5; profile-level-id=15; mode=AAC-hbr; config=%s; "
			"SizeLength=13; IndexLength=3; IndexDeltaLength=3;"
			"\015\012",
				payloadNumber,
				sConfig); 

		// 500 ms max latency for ISMA profile 1
		maxLatency = timeScale / 2;
	}

	/* add this to the track's sdp */
	bool val = MP4AppendHintTrackSdp(mp4File, hintTrackId, sdpBuf);

	free(sConfig);
	free(sdpBuf);
	if (val == false) {
	  MP4DeleteTrack(mp4File, hintTrackId);
	  return false;
	}

	u_int32_t samplesPerPacket = 0;
 
	if (interleave) {
		u_int32_t maxSampleSize =
			MP4GetTrackMaxSampleSize(mp4File, mediaTrackId);

		// compute how many maximum size samples would fit in a packet
		samplesPerPacket = 
			(maxPayloadSize - 2) / (maxSampleSize + 2);

		// can't interleave if this number is 0 or 1
		if (samplesPerPacket < 2) {
			interleave = false;
		}
	}

	bool rc;

	if (interleave) {
		u_int32_t samplesPerGroup = maxLatency / sampleDuration;
		u_int32_t stride;
		stride = samplesPerGroup / samplesPerPacket;

		if (OneByteHeader && stride > 3) stride = 3;
		if (!OneByteHeader && stride > 7) stride = 7;

#if 0
		printf("max latency %llu sampleDuration %llu spg %u spp %u strid %u\n",
		       maxLatency, sampleDuration, samplesPerGroup,
		       samplesPerPacket, stride);
#endif
		rc = MP4AV_AudioInterleaveHinter(
			mp4File, 
			mediaTrackId, 
			hintTrackId,
			sampleDuration, 
			stride,		// stride
			samplesPerPacket,						// bundle
			maxPayloadSize,
			MP4AV_RfcIsmaConcatenator);

	} else {
		rc = MP4AV_AudioConsecutiveHinter(
			mp4File, 
			mediaTrackId, 
			hintTrackId,
			sampleDuration, 
			2,										// perPacketHeaderSize
			2,										// perSampleHeaderSize
			maxLatency / sampleDuration,			// maxSamplesPerPacket
			maxPayloadSize,
			MP4GetSampleSize,
			MP4AV_RfcIsmaConcatenator,
			MP4AV_RfcIsmaFragmenter);
	}

	if (!rc) {
		MP4DeleteTrack(mp4File, hintTrackId);
		return false;
	}

	return true;
}
Ejemplo n.º 4
0
extern "C" MP4TrackId MP4AV_H264_HintTrackCreate (MP4FileHandle mp4File,
						  MP4TrackId mediaTrackId)
{
  MP4TrackId hintTrackId =
    MP4AddHintTrack(mp4File, mediaTrackId);

  if (hintTrackId == MP4_INVALID_TRACK_ID) {
    return MP4_INVALID_TRACK_ID;
  }

  u_int8_t payloadNumber = MP4_SET_DYNAMIC_PAYLOAD;

  // don't include mpeg4-esid
  MP4SetHintTrackRtpPayload(mp4File, hintTrackId, 
			    "H264", &payloadNumber, 0,
			    NULL, true, false);

  /* get the mpeg4 video configuration */
  u_int8_t **pSeq, **pPict ;
  u_int32_t *pSeqSize, *pPictSize;
  char *base64;
  uint32_t profile_level;
  char *sprop = NULL;
  uint32_t ix = 0;

  MP4GetTrackH264SeqPictHeaders(mp4File,
				mediaTrackId,
				&pSeq,
				&pSeqSize,
				&pPict,
				&pPictSize);
				      
  if (pSeqSize && pSeqSize[0] != 0) {
    // we have valid sequence and picture headers
    uint8_t *p = pSeq[0];
    if (*p == 0 && p[1] == 0 && 
	(p[2] == 1 || (p[2] == 0 && p[3] == 0))) {
      if (p[2] == 0) p += 4;
      else p += 3;
    }
    profile_level = p[0] << 16 |
      p[1] << 8 |
      p[2];
    while (pSeqSize[ix] != 0) {
      base64 = MP4BinaryToBase64(pSeq[ix], pSeqSize[ix]);
      if (sprop == NULL) {
	sprop = strdup(base64);
      } else {
	sprop = (char *)realloc(sprop, strlen(sprop) + strlen(base64) + 1 + 1);
	strcat(sprop, ",");
	strcat(sprop, base64);
      }
      free(base64);
      free(pSeq[ix]);
      ix++;
    }
    free(pSeq);
    free(pSeqSize);

    ix = 0;
    while (pPictSize[ix] != 0) {
      base64 = MP4BinaryToBase64(pPict[ix], pPictSize[ix]);
      sprop = (char *)realloc(sprop, strlen(sprop) + strlen(base64) + 1 + 1);
      strcat(sprop, ",");
      strcat(sprop, base64);
      free(base64);
      free(pPict[ix]);
      ix++;
    }
    free(pPict);
    free(pPictSize);

    /* create the appropriate SDP attribute */
    char* sdpBuf = (char*)malloc(strlen(sprop) + 128);
	  
    sprintf(sdpBuf,
	    "a=fmtp:%u profile-level-id=%06x; sprop-parameter-sets=%s; packetization-mode=1\015\012",
	    payloadNumber,
	    profile_level,
	    sprop); 
	  
    /* add this to the track's sdp */
    MP4AppendHintTrackSdp(mp4File, hintTrackId, sdpBuf);
	  
    free(sprop);
    free(sdpBuf);
  }
  return hintTrackId;
}
Ejemplo n.º 5
0
extern "C" MP4TrackId MP4AV_Rfc3016_HintTrackCreate (MP4FileHandle mp4File,
        MP4TrackId mediaTrackId)
{
    MP4TrackId hintTrackId =
        MP4AddHintTrack(mp4File, mediaTrackId);

    if (hintTrackId == MP4_INVALID_TRACK_ID) {
        return MP4_INVALID_TRACK_ID;
    }

    u_int8_t payloadNumber = MP4_SET_DYNAMIC_PAYLOAD;

    if (MP4SetHintTrackRtpPayload(mp4File, hintTrackId,
                                  "MP4V-ES", &payloadNumber, 0) == false) {
        MP4DeleteTrack(mp4File, hintTrackId);
        return MP4_INVALID_TRACK_ID;
    }

    /* get the mpeg4 video configuration */
    u_int8_t* pConfig;
    u_int32_t configSize;
    u_int8_t systemsProfileLevel = 0xFE;

    if (MP4GetTrackESConfiguration(mp4File, mediaTrackId, &pConfig, &configSize) == false) {
        MP4DeleteTrack(mp4File, hintTrackId);
        return MP4_INVALID_TRACK_ID;
    }

    if (pConfig) {
        // attempt to get a valid profile-level
        static u_int8_t voshStartCode[4] = {
            0x00, 0x00, 0x01, MP4AV_MPEG4_VOSH_START
        };
        if (configSize >= 5 && !memcmp(pConfig, voshStartCode, 4)) {
            systemsProfileLevel = pConfig[4];
        }
        if (systemsProfileLevel == 0xFE) {
            u_int8_t iodProfileLevel = MP4GetVideoProfileLevel(mp4File);
            if (iodProfileLevel > 0 && iodProfileLevel < 0xFE) {
                systemsProfileLevel = iodProfileLevel;
            } else {
                systemsProfileLevel = 1;
            }
        }

        /* convert it into ASCII form */
        char* sConfig = MP4BinaryToBase16(pConfig, configSize);
        free(pConfig);
        if (sConfig == NULL) {
            MP4DeleteTrack(mp4File, hintTrackId);
            return MP4_INVALID_TRACK_ID;
        }

        /* create the appropriate SDP attribute */
        char* sdpBuf = (char*)malloc(strlen(sConfig) + 128);

        if (sdpBuf == NULL) {
            free(sConfig);
            MP4DeleteTrack(mp4File, hintTrackId);
            return MP4_INVALID_TRACK_ID;
        }
        snprintf(sdpBuf,
                 strlen(sConfig) + 128,
                 "a=fmtp:%u profile-level-id=%u; config=%s;\015\012",
                 payloadNumber,
                 systemsProfileLevel,
                 sConfig);
        free(sConfig);

        /* add this to the track's sdp */
        if (MP4AppendHintTrackSdp(mp4File, hintTrackId, sdpBuf) == false) {
            MP4DeleteTrack(mp4File, hintTrackId);
            hintTrackId = MP4_INVALID_TRACK_ID;
        }

        free(sdpBuf);
    }
    return hintTrackId;
}
Ejemplo n.º 6
0
extern "C" bool MP4AV_Rfc3016LatmHinter (MP4FileHandle mp4File,
        MP4TrackId mediaTrackId,
        u_int16_t maxPayloadSize)
{
    u_int32_t numSamples = MP4GetTrackNumberOfSamples(mp4File, mediaTrackId);
    u_int32_t maxSampleSize = MP4GetTrackMaxSampleSize(mp4File, mediaTrackId);
    MP4Duration sampleDuration =
        MP4AV_GetAudioSampleDuration(mp4File, mediaTrackId);

    if (sampleDuration == MP4_INVALID_DURATION) {
        return false;
    }

    if (numSamples == 0 || maxSampleSize == 0) {
        return false;
    }


    /* get the mpeg4 video configuration */
    u_int8_t* pAudioSpecificConfig;
    u_int32_t AudioSpecificConfigSize;

    if (MP4GetTrackESConfiguration(mp4File, mediaTrackId,
                                   &pAudioSpecificConfig,
                                   &AudioSpecificConfigSize) == false)
        return false;

    if (pAudioSpecificConfig == NULL ||
            AudioSpecificConfigSize == 0) return false;

    uint8_t channels = MP4AV_AacConfigGetChannels(pAudioSpecificConfig);
    uint32_t freq = MP4AV_AacConfigGetSamplingRate(pAudioSpecificConfig);
    uint8_t type = MP4AV_AacConfigGetAudioObjectType(pAudioSpecificConfig);

    uint8_t *pConfig;
    uint32_t configSize;

    MP4AV_LatmGetConfiguration(&pConfig, &configSize,
                               pAudioSpecificConfig, AudioSpecificConfigSize);
    free(pAudioSpecificConfig);

    if (pConfig == NULL || configSize == 0) {
        CHECK_AND_FREE(pConfig);
        return false;
    }

    MP4TrackId hintTrackId =
        MP4AddHintTrack(mp4File, mediaTrackId);

    if (hintTrackId == MP4_INVALID_TRACK_ID) {
        free(pConfig);
        return false;
    }
    u_int8_t payloadNumber = MP4_SET_DYNAMIC_PAYLOAD;

    char buffer[10];
    if (channels != 1) {
        snprintf(buffer, sizeof(buffer), "%u", channels);
    }

    /* convert it into ASCII form */
    char* sConfig = MP4BinaryToBase16(pConfig, configSize);
    free(pConfig);
    if (sConfig == NULL ||
            MP4SetHintTrackRtpPayload(mp4File, hintTrackId,
                                      "MP4A-LATM", &payloadNumber, 0,
                                      channels != 1 ? buffer : NULL) == false) {
        MP4DeleteTrack(mp4File, hintTrackId);
        return false;
    }

    uint32_t profile_level;
    // from gpac code
    switch (type) {
    case 2:
        if (channels <= 2) profile_level = freq <= 24000 ? 0x28 : 0x29;
        else profile_level = freq <= 48000 ? 0x2a : 0x2b;
        break;
    case 5:
        if (channels <= 2) profile_level = freq < 24000 ? 0x2c : 0x2d;
        else profile_level = freq <= 48000 ? 0x2e : 0x2f;
        break;
    default:
        if (channels <= 2) profile_level = freq < 24000 ? 0x0e : 0x0f;
        else profile_level = 0x10;
        break;
    }

    /* create the appropriate SDP attribute */
    char* sdpBuf = (char*)malloc(strlen(sConfig) + 128);

    if (sdpBuf == NULL) {
        free(sConfig);
        MP4DeleteTrack(mp4File, hintTrackId);
        return false;
    }
    snprintf(sdpBuf,
             strlen(sConfig) + 128,
             "a=fmtp:%u profile-level-id=%u; cpresent=0; config=%s;\015\012",
             payloadNumber,
             profile_level,
             sConfig);

    /* add this to the track's sdp */
    bool val = MP4AppendHintTrackSdp(mp4File, hintTrackId, sdpBuf);

    free(sConfig);
    free(sdpBuf);
    if (val == false) {
        MP4DeleteTrack(mp4File, hintTrackId);
        return false;
    }

    for (MP4SampleId sampleId = 1; sampleId <= numSamples; sampleId++) {
        uint8_t buffer[32];
        uint32_t offset = 0;
        uint32_t sampleSize =
            MP4GetSampleSize(mp4File, mediaTrackId, sampleId);
        uint32_t size_left = sampleSize;

        while (size_left > 0) {
            if (size_left > 0xff) {
                size_left -= 0xff;
                buffer[offset] = 0xff;
            } else {
                buffer[offset] = size_left;
                size_left = 0;
            }
            offset++;
        }
        if (MP4AddRtpHint(mp4File, hintTrackId) == false ||
                MP4AddRtpPacket(mp4File, hintTrackId, true) == false ||
                MP4AddRtpImmediateData(mp4File, hintTrackId,
                                       buffer, offset) == false ||
                MP4AddRtpSampleData(mp4File, hintTrackId,
                                    sampleId, 0, sampleSize) == false ||
                MP4WriteRtpHint(mp4File, hintTrackId, sampleDuration) == false) {
            MP4DeleteTrack(mp4File, hintTrackId);
            return false;
        }
    }
    return true;

}