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."); }
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; }