VALUE _mp4v2_video_init(MP4FileHandle mp4v2, MP4TrackId track_id) { VALUE video = rb_class_new_instance(0, NULL, rb_cVideo); video = _mp4v2_track_init(video, mp4v2, track_id); uint16_t height = MP4GetTrackVideoHeight(mp4v2, track_id); uint16_t width = MP4GetTrackVideoWidth(mp4v2, track_id); rb_ivar_set(video, rb_intern("@height"), INT2FIX(height)); rb_ivar_set(video, rb_intern("@width"), INT2FIX(width)); rb_ivar_set(video, rb_intern("@fps"), DBL2NUM(MP4GetTrackVideoFrameRate(mp4v2, track_id))); return video; }
int CMp4File::create_media (CPlayerSession *psptr, int have_audio_driver, control_callback_vft_t *cc_vft) { uint video_count, video_offset; uint text_count, text_offset; uint audio_count, audio_offset; MP4TrackId trackId; video_query_t *vq; audio_query_t *aq; text_query_t *tq; uint ix; codec_plugin_t *plugin; int ret_value = 0; uint8_t *foo; u_int32_t bufsize; uint32_t verb = MP4GetVerbosity(m_mp4file); MP4SetVerbosity(m_mp4file, verb & ~(MP4_DETAILS_ERROR)); video_count = MP4GetNumberOfTracks(m_mp4file, MP4_VIDEO_TRACK_TYPE); audio_count = MP4GetNumberOfTracks(m_mp4file, MP4_AUDIO_TRACK_TYPE); text_count = MP4GetNumberOfTracks(m_mp4file, MP4_CNTL_TRACK_TYPE); mp4f_message(LOG_DEBUG, "cntl tracks %u", text_count); MP4SetVerbosity(m_mp4file, verb); if (video_count == 0 && audio_count == 0 && text_count == 0) { psptr->set_message("No audio, video or control tracks in file"); return -1; } if (video_count > 0) { vq = (video_query_t *)malloc(sizeof(video_query_t) * video_count); memset(vq, 0, sizeof(video_query_t) * video_count); } else { vq = NULL; } if (have_audio_driver && audio_count > 0) { aq = (audio_query_t *)malloc(sizeof(audio_query_t) * audio_count); memset(aq, 0, sizeof(audio_query_t) * audio_count); } else { aq = NULL; } if (text_count > 0) { tq = (text_query_t *)malloc(sizeof(text_query_t) * text_count); memset(tq, 0, sizeof(text_query_t) * text_count); } else { tq = NULL; } for (ix = 0, video_offset = 0; ix < video_count; ix++) { trackId = MP4FindTrackId(m_mp4file, ix, MP4_VIDEO_TRACK_TYPE); const char *media_data_name; media_data_name = MP4GetTrackMediaDataName(m_mp4file, trackId); // for now, treat mp4v and encv the same vq[video_offset].track_id = trackId; vq[video_offset].stream_type = STREAM_TYPE_MP4_FILE; vq[video_offset].compressor = media_data_name; if (strcasecmp(media_data_name, "mp4v") == 0 || strcasecmp(media_data_name, "encv") == 0) { uint8_t video_type = MP4GetTrackEsdsObjectTypeId(m_mp4file, trackId); uint8_t profileID = MP4GetVideoProfileLevel(m_mp4file, trackId); mp4f_message(LOG_DEBUG, "MP4 - got track %x profile ID %d", trackId, profileID); MP4SetVerbosity(m_mp4file, verb & ~(MP4_DETAILS_ERROR)); MP4GetTrackESConfiguration(m_mp4file, trackId, &foo, &bufsize); MP4SetVerbosity(m_mp4file, verb); vq[video_offset].type = video_type; vq[video_offset].profile = profileID; vq[video_offset].fptr = NULL; vq[video_offset].config = foo; vq[video_offset].config_len = bufsize; } else if (strcasecmp(media_data_name, "avc1") == 0) { uint8_t profile, level; uint8_t **seqheader, **pictheader; uint32_t *pictheadersize, *seqheadersize; uint32_t ix; MP4GetTrackH264ProfileLevel(m_mp4file, trackId, &profile, &level); MP4GetTrackH264SeqPictHeaders(m_mp4file, trackId, &seqheader, &seqheadersize, &pictheader, &pictheadersize); bufsize = 0; for (ix = 0; seqheadersize[ix] != 0; ix++) { bufsize += seqheadersize[ix] + 4; } for (ix = 0; pictheadersize[ix] != 0; ix++) { bufsize += pictheadersize[ix] + 4; } foo = (uint8_t *)malloc(bufsize + 4); memset(foo, 0, bufsize + 4); uint32_t copied = 0; // headers do not have the byte stream start code stored in the file for (ix = 0; seqheadersize[ix] != 0; ix++) { foo[copied] = 0; foo[copied + 1] = 0; foo[copied + 2] = 0; foo[copied + 3] = 1; copied += 4; // add header memcpy(foo + copied, seqheader[ix], seqheadersize[ix]); copied += seqheadersize[ix]; free(seqheader[ix]); } free(seqheader); free(seqheadersize); for (ix = 0; pictheadersize[ix] != 0; ix++) { foo[copied] = 0; foo[copied + 1] = 0; foo[copied + 2] = 0; foo[copied + 3] = 1; copied += 4; // add header memcpy(foo + copied, pictheader[ix], pictheadersize[ix]); copied += pictheadersize[ix]; free(pictheader[ix]); } free(pictheader); free(pictheadersize); vq[video_offset].type = level; vq[video_offset].profile = profile; vq[video_offset].fptr = NULL; vq[video_offset].config = foo; vq[video_offset].config_len = bufsize; } else { MP4GetTrackVideoMetadata(m_mp4file, trackId, &foo, &bufsize); vq[video_offset].config = foo; vq[video_offset].config_len = bufsize; } plugin = check_for_video_codec(vq[video_offset].stream_type, vq[video_offset].compressor, NULL, vq[video_offset].type, vq[video_offset].profile, vq[video_offset].config, vq[video_offset].config_len, &config); if (plugin == NULL) { psptr->set_message("Can't find plugin for video %s type %d, profile %d", vq[video_offset].compressor, vq[video_offset].type, vq[video_offset].profile); m_illegal_video_codec++; ret_value = 1; // possibly memleak for foo here } else { vq[video_offset].h = MP4GetTrackVideoHeight(m_mp4file, trackId); vq[video_offset].w = MP4GetTrackVideoWidth(m_mp4file, trackId); vq[video_offset].frame_rate = MP4GetTrackVideoFrameRate(m_mp4file, trackId); vq[video_offset].enabled = 0; vq[video_offset].reference = NULL; video_offset++; } } audio_offset = 0; if (have_audio_driver) { for (ix = 0; ix < audio_count; ix++) { trackId = MP4FindTrackId(m_mp4file, ix, MP4_AUDIO_TRACK_TYPE); const char *media_data_name; media_data_name = MP4GetTrackMediaDataName(m_mp4file, trackId); aq[audio_offset].track_id = trackId; aq[audio_offset].stream_type = STREAM_TYPE_MP4_FILE; aq[audio_offset].compressor = media_data_name; if (strcasecmp(media_data_name, "mp4a") == 0 || strcasecmp(media_data_name, "enca") == 0) { uint8_t *userdata = NULL; u_int32_t userdata_size; aq[audio_offset].type = MP4GetTrackEsdsObjectTypeId(m_mp4file, trackId); MP4SetVerbosity(m_mp4file, verb & ~(MP4_DETAILS_ERROR)); aq[audio_offset].profile = MP4GetAudioProfileLevel(m_mp4file); MP4GetTrackESConfiguration(m_mp4file, trackId, &userdata, &userdata_size); MP4SetVerbosity(m_mp4file, verb); aq[audio_offset].config = userdata; aq[audio_offset].config_len = userdata_size; } plugin = check_for_audio_codec(aq[audio_offset].stream_type, aq[audio_offset].compressor, NULL, aq[audio_offset].type, aq[audio_offset].profile, aq[audio_offset].config, aq[audio_offset].config_len, &config); if (plugin != NULL) { aq[audio_offset].fptr = NULL; aq[audio_offset].sampling_freq = MP4GetTrackTimeScale(m_mp4file, trackId); MP4SetVerbosity(m_mp4file, verb & ~(MP4_DETAILS_ERROR)); aq[audio_offset].chans = MP4GetTrackAudioChannels(m_mp4file, trackId); MP4SetVerbosity(m_mp4file, verb); aq[audio_offset].enabled = 0; aq[audio_offset].reference = NULL; audio_offset++; m_have_audio = true; } else { m_illegal_audio_codec++; ret_value = 1; } } } else { if (audio_count) ret_value = 1; } text_offset = 0; for (ix = 0; ix < text_count; ix++) { trackId = MP4FindTrackId(m_mp4file, ix, MP4_CNTL_TRACK_TYPE); const char *media_data_name; media_data_name = MP4GetTrackMediaDataName(m_mp4file, trackId); tq[text_offset].track_id = trackId; tq[text_offset].stream_type = STREAM_TYPE_MP4_FILE; tq[text_offset].compressor = media_data_name; plugin = check_for_text_codec(tq[text_offset].stream_type, tq[text_offset].compressor, NULL, NULL, 0, &config); if (plugin != NULL) { tq[text_offset].fptr = NULL; tq[text_offset].enabled = 0; tq[text_offset].reference = NULL; text_offset++; } else { m_illegal_text_codec++; ret_value = 1; } } if (video_offset == 0 && audio_offset == 0 && text_offset == 0) { psptr->set_message("No playable codecs in mp4 file"); return -1; } if (cc_vft && cc_vft->media_list_query != NULL) { (cc_vft->media_list_query)(psptr, video_offset, vq, audio_offset, aq, text_offset, tq); } else { if (video_offset > 0) { vq[0].enabled = 1; } if (audio_offset > 0) { aq[0].enabled = 1; } if (text_offset > 0) { tq[0].enabled = 1; } } int vidret, audret, textret; uint start_desc = 1; vidret = create_video(psptr, vq, video_offset, start_desc); free(vq); if (vidret < 0) { free(aq); free(tq); return -1; } audret = create_audio(psptr, aq, audio_offset, start_desc); free(aq); textret = create_text(psptr, tq, text_offset, start_desc); free(tq); if (audret < 0 || textret < 0) ret_value = -1; char *name; verb = MP4GetVerbosity(m_mp4file); MP4SetVerbosity(m_mp4file, verb & ~(MP4_DETAILS_ERROR)); if (MP4GetMetadataName(m_mp4file, &name) && name != NULL) { psptr->set_session_desc(0, name); free(name); } MP4SetVerbosity(m_mp4file, verb); return (ret_value); }
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; }
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; }
unsigned int GetVideoHeight() const { return MP4GetTrackVideoHeight(handle, video_track_id); }
static char* PrintVideoInfo( MP4FileHandle mp4File, MP4TrackId trackId) { static const u_int8_t mpegVideoTypes[] = { MP4_MPEG2_SIMPLE_VIDEO_TYPE, // 0x60 MP4_MPEG2_MAIN_VIDEO_TYPE, // 0x61 MP4_MPEG2_SNR_VIDEO_TYPE, // 0x62 MP4_MPEG2_SPATIAL_VIDEO_TYPE, // 0x63 MP4_MPEG2_HIGH_VIDEO_TYPE, // 0x64 MP4_MPEG2_442_VIDEO_TYPE, // 0x65 MP4_MPEG1_VIDEO_TYPE, // 0x6A MP4_JPEG_VIDEO_TYPE, // 0x6C MP4_YUV12_VIDEO_TYPE, MP4_H263_VIDEO_TYPE, MP4_H261_VIDEO_TYPE, }; static const char* mpegVideoNames[] = { "MPEG-2 Simple", "MPEG-2 Main", "MPEG-2 SNR", "MPEG-2 Spatial", "MPEG-2 High", "MPEG-2 4:2:2", "MPEG-1", "JPEG", "YUV12", "H.263", "H.261", }; u_int8_t numMpegVideoTypes = sizeof(mpegVideoTypes) / sizeof(u_int8_t); bool foundTypeName = false; const char* typeName = "Unknown"; const char *media_data_name; char originalFormat[8]; char oformatbuffer[32]; originalFormat[0] = 0; *oformatbuffer = 0; uint8_t type = 0; media_data_name = MP4GetTrackMediaDataName(mp4File, trackId); // encv 264b if (strcasecmp(media_data_name, "encv") == 0) { if (MP4GetTrackMediaDataOriginalFormat(mp4File, trackId, originalFormat, sizeof(originalFormat)) == false) media_data_name = NULL; } char typebuffer[80]; if (media_data_name == NULL) { typeName = "Unknown - no media data name"; foundTypeName = true; } else if ((strcasecmp(media_data_name, "avc1") == 0) || (strcasecmp(originalFormat, "264b") == 0)) { // avc uint8_t profile, level; char profileb[20], levelb[20]; if (MP4GetTrackH264ProfileLevel(mp4File, trackId, &profile, &level)) { if (profile == 66) { strcpy(profileb, "Baseline"); } else if (profile == 77) { strcpy(profileb, "Main"); } else if (profile == 88) { strcpy(profileb, "Extended"); } else if (profile == 100) { strcpy(profileb, "High"); } else if (profile == 110) { strcpy(profileb, "High 10"); } else if (profile == 122) { strcpy(profileb, "High 4:2:2"); } else if (profile == 144) { strcpy(profileb, "High 4:4:4"); } else { snprintf(profileb, 20, "Unknown Profile %x", profile); } switch (level) { case 10: case 20: case 30: case 40: case 50: snprintf(levelb, 20, "%u", level / 10); break; case 11: case 12: case 13: case 21: case 22: case 31: case 32: case 41: case 42: case 51: snprintf(levelb, 20, "%u.%u", level / 10, level % 10); break; default: snprintf(levelb, 20, "unknown level %x", level); break; } if (originalFormat != NULL && originalFormat[0] != '\0') snprintf(oformatbuffer, 32, "(%s) ", originalFormat); snprintf(typebuffer, sizeof(typebuffer), "H264 %s%s@%s", oformatbuffer, profileb, levelb); typeName = typebuffer; } else { typeName = "H.264 - profile/level error"; } foundTypeName = true; } else if (strcasecmp(media_data_name, "s263") == 0) { // 3gp h.263 typeName = "H.263"; foundTypeName = true; } else if ((strcasecmp(media_data_name, "mp4v") == 0) || (strcasecmp(media_data_name, "encv") == 0)) { // note encv might needs it's own field eventually. type = MP4GetTrackEsdsObjectTypeId(mp4File, trackId); if (type == MP4_MPEG4_VIDEO_TYPE) { type = MP4GetVideoProfileLevel(mp4File, trackId); typeName = Mpeg4VisualProfileName(type); if (typeName == NULL) { typeName = "MPEG-4 Unknown Profile"; } else { foundTypeName = true; } } else { for (u_int8_t i = 0; i < numMpegVideoTypes; i++) { if (type == mpegVideoTypes[i]) { typeName = mpegVideoNames[i]; foundTypeName = true; break; } } } } else { typeName = media_data_name; foundTypeName = true; // we don't have a type value to display } MP4Duration trackDuration = MP4GetTrackDuration(mp4File, trackId); double msDuration = UINT64_TO_DOUBLE(MP4ConvertFromTrackDuration(mp4File, trackId, trackDuration, MP4_MSECS_TIME_SCALE)); u_int32_t avgBitRate = MP4GetTrackBitRate(mp4File, trackId); // Note not all mp4 implementations set width and height correctly // The real answer can be buried inside the ES configuration info u_int16_t width = MP4GetTrackVideoWidth(mp4File, trackId); u_int16_t height = MP4GetTrackVideoHeight(mp4File, trackId); double fps = MP4GetTrackVideoFrameRate(mp4File, trackId); char *sInfo = (char*)MP4Malloc(256); // type duration avgBitrate frameSize frameRate if (foundTypeName) { sprintf(sInfo, "%u\tvideo\t%s%s, %.3f secs, %u kbps, %ux%u @ %f fps\n", trackId, MP4IsIsmaCrypMediaTrack(mp4File, trackId) ? "encv - " : "", typeName, msDuration / 1000.0, (avgBitRate + 500) / 1000, width, height, fps ); } else { sprintf(sInfo, "%u\tvideo\t%s(%u), %.3f secs, %u kbps, %ux%u @ %f fps\n", trackId, typeName, type, msDuration / 1000.0, (avgBitRate + 500) / 1000, width, height, fps ); } return sInfo; }
static GtkWidget* CreateMp4TrackMenu( GtkWidget* menu, char type, const char* source, u_int32_t* pIndex, u_int32_t* pNumber, u_int32_t** ppValues) { *pIndex = 0; u_int32_t newTrackNumber = 1; MP4FileHandle mp4File = MP4Read(source); char* trackType = NULL; if (mp4File) { if (type == 'V') { trackType = MP4_VIDEO_TRACK_TYPE; } else { trackType = MP4_AUDIO_TRACK_TYPE; } newTrackNumber = MP4GetNumberOfTracks(mp4File, trackType); } u_int32_t* newTrackValues = (u_int32_t*)malloc(sizeof(u_int32_t) * newTrackNumber); char** newTrackNames = (char**)malloc(sizeof(char*) * newTrackNumber); if (!mp4File) { newTrackValues[0] = 0; newTrackNames[0] = strdup(""); } else { for (u_int8_t i = 0; i < newTrackNumber; i++) { MP4TrackId trackId = MP4FindTrackId(mp4File, i, trackType); char* trackName = "Unknown"; char buf[64]; if (trackType == MP4_VIDEO_TRACK_TYPE) { u_int8_t videoType = MP4GetTrackEsdsObjectTypeId(mp4File, trackId); switch (videoType) { case MP4_MPEG1_VIDEO_TYPE: trackName = "MPEG1"; break; case MP4_MPEG2_SIMPLE_VIDEO_TYPE: case MP4_MPEG2_MAIN_VIDEO_TYPE: case MP4_MPEG2_SNR_VIDEO_TYPE: case MP4_MPEG2_SPATIAL_VIDEO_TYPE: case MP4_MPEG2_HIGH_VIDEO_TYPE: case MP4_MPEG2_442_VIDEO_TYPE: trackName = "MPEG2"; break; case MP4_MPEG4_VIDEO_TYPE: trackName = "MPEG4"; break; case MP4_YUV12_VIDEO_TYPE: trackName = "YUV12"; break; case MP4_H263_VIDEO_TYPE: trackName = "H263"; break; case MP4_H261_VIDEO_TYPE: trackName = "H261"; break; } snprintf(buf, sizeof(buf), "%u - %s %u x %u %.2f fps %u kbps", trackId, trackName, MP4GetTrackVideoWidth(mp4File, trackId), MP4GetTrackVideoHeight(mp4File, trackId), MP4GetTrackVideoFrameRate(mp4File, trackId), (MP4GetTrackBitRate(mp4File, trackId) + 500) / 1000); } else { // audio u_int8_t audioType = MP4GetTrackEsdsObjectTypeId(mp4File, trackId); switch (audioType) { case MP4_MPEG1_AUDIO_TYPE: case MP4_MPEG2_AUDIO_TYPE: trackName = "MPEG (MP3)"; break; case MP4_MPEG2_AAC_MAIN_AUDIO_TYPE: case MP4_MPEG2_AAC_LC_AUDIO_TYPE: case MP4_MPEG2_AAC_SSR_AUDIO_TYPE: case MP4_MPEG4_AUDIO_TYPE: trackName = "AAC"; break; case MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE: trackName = "PCM16 LITTLE ENDIAN"; break; case MP4_PCM16_BIG_ENDIAN_AUDIO_TYPE: trackName = "PCM16 BIG ENDIAN"; case MP4_AC3_AUDIO_TYPE: trackName = "AC3"; break; case MP4_VORBIS_AUDIO_TYPE: trackName = "Ogg Vorbis"; break; case MP4_ALAW_AUDIO_TYPE: trackName = "G711 aLaw"; break; case MP4_ULAW_AUDIO_TYPE: trackName = "G711 uLaw"; break; } snprintf(buf, sizeof(buf), "%u - %s %u kbps", trackId, trackName, (MP4GetTrackBitRate(mp4File, trackId) + 500) / 1000); } newTrackValues[i] = trackId; newTrackNames[i] = strdup(buf); } MP4Close(mp4File); } // (re)create the menu menu = CreateOptionMenu( menu, newTrackNames, newTrackNumber, *pIndex, GTK_SIGNAL_FUNC(on_track_menu_activate)); // free up old names for (u_int8_t i = 0; i < *pNumber; i++) { free(trackNames[i]); } free(trackNames); free(*ppValues); *pNumber = newTrackNumber; trackNames = newTrackNames; *ppValues = newTrackValues; return menu; }
DWORD MP4Streamer::GetVideoHeight() { return MP4GetTrackVideoHeight(video->mp4,video->track); }