void Context::getTracks(const char * file)
	{
		int i = 0;
		bool audioTrack = false, videoTrack = false;

		if (!isOpen()) throw Exception(file, "File is closed.");

		for (;;)
		{
			TrackProperties track;
			if((track.hint = MP4FindTrackId(fh, i++, MP4_HINT_TRACK_TYPE, 0)) == MP4_INVALID_TRACK_ID) break;

			MP4GetHintTrackRtpPayload(fh, track.hint, &track.codecName, &track.payload, NULL, NULL);

			track.track = MP4GetHintTrackReferenceTrackId(fh, track.hint);
			if(track.track == MP4_INVALID_TRACK_ID) continue;
			track.clock = MP4GetTrackTimeScale(fh, track.hint);

			if (!strcmp(MP4GetTrackType(fh, track.track), MP4_AUDIO_TRACK_TYPE)) {
				audioTrack = true;

				if(!strncmp(track.codecName, "PCM", 3))
					track.packetLength = 20;
				else
					track.packetLength = track.clock = 0;

				audio = track;
			} else if (!strcmp(MP4GetTrackType(fh, track.track), MP4_VIDEO_TRACK_TYPE)) {
				videoTrack = true;

				const char * sdp = MP4GetHintTrackSdp(fh, track.hint);
				const char * fmtp = strstr(sdp, "fmtp");

				if (fmtp) {
					// finds beginning of 'fmtp' value;
					for(fmtp += 5; *fmtp != ' '; ++fmtp);
					++fmtp;

					const char * eol = fmtp;
					for(;*eol != '\r' && *eol != '\n'; ++eol);
					video.fmtp = std::string(fmtp, eol);
				}
				video.track = track;
			}
		}

		if (!audioTrack || !videoTrack) throw Exception(file, "Missing audio/video track.");
	}
Beispiel #2
0
static char* PrintHintInfo(
	MP4FileHandle mp4File,
	MP4TrackId trackId)
{
	MP4TrackId referenceTrackId =
		MP4GetHintTrackReferenceTrackId(mp4File, trackId);

	char* payloadName = NULL;
	if (!MP4GetHintTrackRtpPayload(mp4File, trackId, &payloadName))
	  return NULL;

	char *sInfo = (char*)MP4Malloc(256);

	snprintf(sInfo, 256, 
		"%u\thint\tPayload %s for track %u\n",
		trackId,
		payloadName,
		referenceTrackId);

	free(payloadName);

	return sInfo;
}
int MP4Streamer::Open(const char *filename)
{
	//LOg
	Log(">MP4 opening [%s]\n",filename);

	//Lock
	pthread_mutex_lock(&mutex);

	//If already opened
	if (opened)
	{
		//Unlock
		pthread_mutex_unlock(&mutex);
		//Return error
		return Error("Already opened\n");
	}
	
	// Open mp4 file
	mp4 = MP4Read(filename);

	// If not valid
	if (mp4 == MP4_INVALID_FILE_HANDLE)
	{
		//Unlock
		pthread_mutex_unlock(&mutex);
		//Return error
		return Error("Invalid file handle for %s\n",filename);
	}
	
	//No tracks
	audio = NULL;
	video = NULL;
	text = NULL;

	//Iterate thougth tracks
	DWORD i = 0;

	// Get the first hint track
	MP4TrackId hintId = MP4_INVALID_TRACK_ID;

	// Iterate hint tracks
	do
	{
		// Get the next hint track
		hintId = MP4FindTrackId(mp4, i++, MP4_HINT_TRACK_TYPE, 0);

		Log("-Found hint track [hintId:%d]\n", hintId);

		// Get asociated track
		MP4TrackId trackId = MP4GetHintTrackReferenceTrackId(mp4, hintId);

		// Check it's good
		if (trackId != MP4_INVALID_TRACK_ID)
		{
			// Get track type
			const char *type = MP4GetTrackType(mp4, trackId);

			// Get rtp track
			char *name;
			BYTE payload;
			MP4GetHintTrackRtpPayload(mp4, hintId, &name, &payload, NULL, NULL);

			Log("-Streaming media [trackId:%d,type:\"%s\",name:\"%s\",payload:%d]\n", trackId, type, name, payload);

			// Check track type
			if ((strcmp(type, MP4_AUDIO_TRACK_TYPE) == 0) && !audio)
			{
				// Depending on the name
				if (strcmp("PCMU", name) == 0)
					//Create new audio track
					audio = new MP4RtpTrack(MediaFrame::Audio,AudioCodec::PCMU,payload);
				else if (strcmp("PCMA", name) == 0)
					//Create new audio track
					audio = new MP4RtpTrack(MediaFrame::Audio,AudioCodec::PCMA,payload);
				else
					//Skip
					continue;

				// Get time scale
				audio->timeScale = MP4GetTrackTimeScale(mp4, hintId);

				//Store the other values
				audio->mp4 = mp4;
				audio->hint = hintId;
				audio->track = trackId;
				audio->sampleId = 1;
				audio->packetIndex = 0;

			} else if ((strcmp(type, MP4_VIDEO_TRACK_TYPE) == 0) && !video) {
				// Depending on the name
				if (strcmp("H263", name) == 0)
					//Create new video track
					video = new MP4RtpTrack(MediaFrame::Video,VideoCodec::H263_1996,payload);
				else if (strcmp("H263-1998", name) == 0)
					//Create new video track
					video = new MP4RtpTrack(MediaFrame::Video,VideoCodec::H263_1998,payload);
				else if (strcmp("H263-2000", name) == 0)
					//Create new video track
					video = new MP4RtpTrack(MediaFrame::Video,VideoCodec::H263_1998,payload);
				else if (strcmp("H264", name) == 0)
					//Create new video track
					video = new MP4RtpTrack(MediaFrame::Video,VideoCodec::H264,payload);
				else
					continue;
					
				// Get time scale
				video->timeScale = MP4GetTrackTimeScale(mp4, hintId);
				// it's video
				video->mp4 = mp4;
				video->hint = hintId;
				video->track = trackId;
				video->sampleId = 1;
				video->packetIndex = 0;
			}
		} 
	} while (hintId != MP4_INVALID_TRACK_ID);

	// Get the first text
	MP4TrackId textId = MP4FindTrackId(mp4, 0, MP4_TEXT_TRACK_TYPE, 0);

	Log("-Found text track [%d]\n",textId);

	// Iterate hint tracks
	if (textId != MP4_INVALID_TRACK_ID)
	{
		//We have it
		text = new MP4TextTrack();
		//Set values
		text->mp4 = mp4;
		text->track = textId;
		text->sampleId = 1;
		// Get time scale
		text->timeScale = MP4GetTrackTimeScale(mp4, textId);
	}

	//We are opened
	opened = true;

	//Unlock
	pthread_mutex_unlock(&mutex);
	
	return 1;
}