Пример #1
0
bool MP4AV_RfcIsmaFragmenter(
	MP4FileHandle mp4File, 
	MP4TrackId mediaTrackId, 
	MP4TrackId hintTrackId,
	MP4SampleId sampleId, 
	u_int32_t sampleSize, 
	MP4Duration sampleDuration,
	u_int16_t maxPayloadSize)
{
  if (MP4AddRtpHint(mp4File, hintTrackId) == false ||
      MP4AddRtpPacket(mp4File, hintTrackId, false) == false) 
    return false;

  // Note: CELP is never fragmented
  // so we assume the two byte AAC-hbr payload header
  u_int8_t payloadHeader[4];
  payloadHeader[0] = 0;
  payloadHeader[1] = 16;
  payloadHeader[2] = sampleSize >> 5;
  payloadHeader[3] = (sampleSize & 0x1F) << 3;

  if (MP4AddRtpImmediateData(mp4File, hintTrackId,
			     (u_int8_t*)&payloadHeader, 
			     sizeof(payloadHeader)) == false) 
    return false;

  u_int16_t sampleOffset = 0;
  u_int16_t fragLength = maxPayloadSize - 4;

  do {
    if (MP4AddRtpSampleData(mp4File, hintTrackId,
			    sampleId, 
			    sampleOffset, 
			    fragLength) == false) return false;

    sampleOffset += fragLength;

    if (sampleSize - sampleOffset > maxPayloadSize) {
      fragLength = maxPayloadSize; 
      if (MP4AddRtpPacket(mp4File, hintTrackId, false) == false) return false;
    } else {
      fragLength = sampleSize - sampleOffset; 
      if (fragLength) {
	if (MP4AddRtpPacket(mp4File, hintTrackId, true) == false) return false;
      }
    }
  } while (sampleOffset < sampleSize);

  return MP4WriteRtpHint(mp4File, hintTrackId, sampleDuration);
}
Пример #2
0
//#define DEBUG_G711 1
extern "C" bool G711Hinter (MP4FileHandle mp4file, 
			    MP4TrackId trackid,
			    uint16_t maxPayloadSize)
{
  uint32_t numSamples;
  uint8_t audioType;
  MP4SampleId sampleId;
  uint32_t sampleSize;
  MP4TrackId hintTrackId;
  uint8_t payload;
  uint32_t bytes_this_hint;
  uint32_t sampleOffset;

  numSamples = MP4GetTrackNumberOfSamples(mp4file, trackid);

  if (numSamples == 0) return false;

  audioType = MP4GetTrackEsdsObjectTypeId(mp4file, trackid);

  if (audioType != MP4_ALAW_AUDIO_TYPE &&
      audioType != MP4_ULAW_AUDIO_TYPE) return false;

  hintTrackId = MP4AddHintTrack(mp4file, trackid);

  if (hintTrackId == MP4_INVALID_TRACK_ID) {
    return false;
  }
  const char *type;

  if (audioType == MP4_ALAW_AUDIO_TYPE) {
    payload = 8;
    type = "PCMA";
  } else {
    payload = 0;
    type = "PCMU";
  }

  MP4SetHintTrackRtpPayload(mp4file, hintTrackId, type, &payload, 0,NULL,
			    false);

  MP4Duration sampleDuration;
  bool have_skip;
  sampleId = 1;
  sampleSize = MP4GetSampleSize(mp4file, trackid, sampleId);
  sampleDuration = MP4GetSampleDuration(mp4file, trackid, sampleId);
  have_skip = sampleDuration != sampleSize;
  sampleOffset = 0;
  bytes_this_hint = 0;

  if (maxPayloadSize > 160) maxPayloadSize = 160;

  while (1) {
    if (bytes_this_hint == 0) {
#ifdef DEBUG_G711
      printf("Adding hint/packet\n");
#endif
      MP4AddRtpHint(mp4file, hintTrackId);
      MP4AddRtpPacket(mp4file, hintTrackId, false); // marker bit 0
    }
    uint16_t bytes_left_this_packet;
    bytes_left_this_packet = maxPayloadSize - bytes_this_hint;
    if (sampleSize >= bytes_left_this_packet) {
      MP4AddRtpSampleData(mp4file, hintTrackId, 
			  sampleId, sampleOffset, bytes_left_this_packet);
      bytes_this_hint += bytes_left_this_packet;
      sampleSize -= bytes_left_this_packet;
      sampleOffset += bytes_left_this_packet;
#ifdef DEBUG_G711
      printf("Added sample with %u bytes\n", bytes_left_this_packet);
#endif
    } else {
      MP4AddRtpSampleData(mp4file, hintTrackId, 
			  sampleId, sampleOffset, sampleSize);
      bytes_this_hint += sampleSize;
#ifdef DEBUG_G711
      printf("Added sample with %u bytes\n", sampleSize);
#endif
      sampleSize = 0;
    }

    if (bytes_this_hint >= maxPayloadSize) {
      // Write the hint
      // duration is bytes written
      MP4WriteRtpHint(mp4file, hintTrackId, bytes_this_hint);
#ifdef DEBUG_G711
      printf("Finished packet - bytes %u\n", bytes_this_hint);
#endif
      bytes_this_hint = 0;
    }
    if (sampleSize == 0) {
      // next sample
      if (have_skip && bytes_this_hint != 0) {
#ifdef DEBUG_G711
	printf("duration - ending packet - bytes %u\n", bytes_this_hint);
#endif
	MP4WriteRtpHint(mp4file, hintTrackId, bytes_this_hint);
	bytes_this_hint = 0;
      }
      sampleId++;
      if (sampleId > numSamples) {
	// finish it and exit
	if (bytes_this_hint != 0) {
	  MP4WriteRtpHint(mp4file, hintTrackId, bytes_this_hint);
	}
	return true;
      }
      sampleSize = MP4GetSampleSize(mp4file, trackid, sampleId);
      sampleDuration = MP4GetSampleDuration(mp4file, trackid, sampleId);
      have_skip = sampleDuration != sampleSize;
#ifdef DEBUG_G711
      printf("Next sample %u - size %u %u\n", sampleId, sampleSize,
	     have_skip);
#endif
      sampleOffset = 0;
    }
  }
	
  return true; // will never reach here
}
Пример #3
0
bool MP4AV_RfcIsmaConcatenator(
	MP4FileHandle mp4File, 
	MP4TrackId mediaTrackId, 
	MP4TrackId hintTrackId,
	u_int8_t samplesThisHint, 
	MP4SampleId* pSampleIds, 
	MP4Duration hintDuration,
	u_int16_t maxPayloadSize)
{
  // handle degenerate case
  if (samplesThisHint == 0) {
    return true;
  }

  u_int8_t auPayloadHdrSize;

  // LATER would be more efficient if this were a parameter
  u_int8_t mpeg4AudioType =
    MP4GetTrackAudioMpeg4Type(mp4File, mediaTrackId);

  if (mpeg4AudioType == MP4_MPEG4_CELP_AUDIO_TYPE) {
    auPayloadHdrSize = 1;
  } else {
    auPayloadHdrSize = 2;
  }

  // construct the new hint
  if (MP4AddRtpHint(mp4File, hintTrackId) == false ||
      MP4AddRtpPacket(mp4File, hintTrackId, true) == false) return false;

  u_int8_t payloadHeader[2];

  u_int16_t numHdrBits = samplesThisHint * auPayloadHdrSize * 8;
  payloadHeader[0] = numHdrBits >> 8;
  payloadHeader[1] = numHdrBits & 0xFF;

  if (MP4AddRtpImmediateData(mp4File, hintTrackId,
			     (u_int8_t*)&payloadHeader, 
			     sizeof(payloadHeader)) == false) return false;

  u_int8_t i;

  // first the headers
  for (i = 0; i < samplesThisHint; i++) {
    MP4SampleId sampleId = pSampleIds[i];

    u_int32_t sampleSize = 
      MP4GetSampleSize(mp4File, mediaTrackId, sampleId);

    if (auPayloadHdrSize == 1) {
      // AU payload header is 6 bits of size
      // follow by 2 bits of the difference between sampleId's - 1
      payloadHeader[0] = sampleSize << 2;

    } else { // auPayloadHdrSize == 2
      // AU payload header is 13 bits of size
      // follow by 3 bits of the difference between sampleId's - 1
      payloadHeader[0] = sampleSize >> 5;
      payloadHeader[1] = (sampleSize & 0x1F) << 3;
    }

    if (i > 0) {
      payloadHeader[auPayloadHdrSize - 1] 
	|= ((sampleId - pSampleIds[i-1]) - 1); 
    }
#if 0
    printf("sample %u size %u %02x %02x prev sample %d\n", 
	   sampleId, sampleSize, payloadHeader[0],
	   payloadHeader[1], pSampleIds[i-1]);
#endif

    if (MP4AddRtpImmediateData(mp4File, hintTrackId,
			       (u_int8_t*)&payloadHeader, 
			       auPayloadHdrSize) == false) 
      return false;
  }

  // then the samples
  for (i = 0; i < samplesThisHint; i++) {
    MP4SampleId sampleId = pSampleIds[i];

    u_int32_t sampleSize = 
      MP4GetSampleSize(mp4File, mediaTrackId, sampleId);

    if (MP4AddRtpSampleData(mp4File, hintTrackId, 
			    sampleId, 0, sampleSize) == false) return false;
  }

  // write the hint
  return MP4WriteRtpHint(mp4File, hintTrackId, hintDuration);
}
Пример #4
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;

}