Exemplo n.º 1
0
media_desc_t *faac_create_audio_sdp (CAudioProfile *pConfig,
				     bool *mpeg4,
				     bool *isma_compliant,
				     uint8_t *audioProfile,
				     uint8_t **audioConfig,
				     uint32_t *audioConfigLen)
{
  media_desc_t *sdpMediaAudio;
  format_list_t *sdpMediaAudioFormat;
  rtpmap_desc_t *sdpAudioRtpMap;
  char audioFmtpBuf[512];

  faac_mp4_fileinfo(pConfig, mpeg4, isma_compliant, audioProfile, audioConfig,
 	    audioConfigLen, NULL);

  sdpMediaAudio = MALLOC_STRUCTURE(media_desc_t);
  memset(sdpMediaAudio, 0, sizeof(*sdpMediaAudio));

  sdpMediaAudioFormat = MALLOC_STRUCTURE(format_list_t);
  memset(sdpMediaAudioFormat, 0, sizeof(*sdpMediaAudioFormat));

  sdpMediaAudioFormat->media = sdpMediaAudio;
  sdpMediaAudioFormat->fmt = strdup("97");

  sdpAudioRtpMap = MALLOC_STRUCTURE(rtpmap_desc_t);
  memset(sdpAudioRtpMap, 0, sizeof(*sdpAudioRtpMap));
  sdpAudioRtpMap->clock_rate = pConfig->GetIntegerValue(CFG_AUDIO_SAMPLE_RATE);

  char* sConfig = MP4BinaryToBase16(*audioConfig, *audioConfigLen);
  if(pConfig->GetBoolValue(CFG_RTP_RFC3016)) {
    sdpAudioRtpMap->encode_name = strdup("MP4A-LATM");
    sprintf(audioFmtpBuf, "profile-level-id=15;object=2;cpresent=0; config=%s ", sConfig); 

  } else {
    sdp_add_string_to_list(&sdpMediaAudio->unparsed_a_lines, "a=mpeg4-esid:10");
    sdpAudioRtpMap->encode_name = strdup("mpeg4-generic");

    sprintf(audioFmtpBuf,
	    "streamtype=5; profile-level-id=15; mode=AAC-hbr; config=%s; "
	    "SizeLength=13; IndexLength=3; IndexDeltaLength=3; Profile=1;",
	    sConfig); 
  }

  free(sConfig);
  sdpMediaAudioFormat->fmt_param = strdup(audioFmtpBuf);
  sdpMediaAudioFormat->rtpmap = sdpAudioRtpMap;
  sdpMediaAudio->fmt = sdpMediaAudioFormat;

  return sdpMediaAudio;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
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;
}
Exemplo n.º 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;

}