diff options
Diffstat (limited to 'debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4info.cpp')
-rw-r--r-- | debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4info.cpp | 625 |
1 files changed, 625 insertions, 0 deletions
diff --git a/debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4info.cpp b/debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4info.cpp new file mode 100644 index 00000000..44bf45e5 --- /dev/null +++ b/debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4info.cpp @@ -0,0 +1,625 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001-2002. All Rights Reserved. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Bill May wmay@cisco.com + * Alix Marchandise-Franquet alix@cisco.com + * Ximpo Group Ltd. mp4v2@ximpo.com + */ + +#include "src/impl.h" + +namespace mp4v2 { namespace impl { + +/////////////////////////////////////////////////////////////////////////////// + +static char* PrintAudioInfo( + MP4FileHandle mp4File, + MP4TrackId trackId) +{ + static const char* mpeg4AudioNames[] = { + "MPEG-4 AAC main", + "MPEG-4 AAC LC", + "MPEG-4 AAC SSR", + "MPEG-4 AAC LTP", + "MPEG-4 AAC HE", + "MPEG-4 AAC Scalable", + "MPEG-4 TwinVQ", + "MPEG-4 CELP", + "MPEG-4 HVXC", + NULL, NULL, + "MPEG-4 TTSI", + "MPEG-4 Main Synthetic", + "MPEG-4 Wavetable Syn", + "MPEG-4 General MIDI", + "MPEG-4 Algo Syn and Audio FX", + "MPEG-4 ER AAC LC", + NULL, + "MPEG-4 ER AAC LTP", + "MPEG-4 ER AAC Scalable", + "MPEG-4 ER TwinVQ", + "MPEG-4 ER BSAC", + "MPEG-4 ER ACC LD", + "MPEG-4 ER CELP", + "MPEG-4 ER HVXC", + "MPEG-4 ER HILN", + "MPEG-4 ER Parametric", + "MPEG-4 SSC", + "MPEG-4 PS", + "MPEG-4 MPEG Surround", + NULL, + "MPEG-4 Layer-1", + "MPEG-4 Layer-2", + "MPEG-4 Layer-3", + "MPEG-4 DST", + "MPEG-4 Audio Lossless", + "MPEG-4 SLS", + "MPEG-4 SLS non-core", + }; + + static const uint8_t mpegAudioTypes[] = { + MP4_MPEG2_AAC_MAIN_AUDIO_TYPE, // 0x66 + MP4_MPEG2_AAC_LC_AUDIO_TYPE, // 0x67 + MP4_MPEG2_AAC_SSR_AUDIO_TYPE, // 0x68 + MP4_MPEG2_AUDIO_TYPE, // 0x69 + MP4_MPEG1_AUDIO_TYPE, // 0x6B + // private types + MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE, + MP4_VORBIS_AUDIO_TYPE, + MP4_ALAW_AUDIO_TYPE, + MP4_ULAW_AUDIO_TYPE, + MP4_G723_AUDIO_TYPE, + MP4_PCM16_BIG_ENDIAN_AUDIO_TYPE, + }; + static const char* mpegAudioNames[] = { + "MPEG-2 AAC Main", + "MPEG-2 AAC LC", + "MPEG-2 AAC SSR", + "MPEG-2 Audio (13818-3)", + "MPEG-1 Audio (11172-3)", + // private types + "PCM16 (little endian)", + "Vorbis", + "G.711 aLaw", + "G.711 uLaw", + "G.723.1", + "PCM16 (big endian)", + }; + uint8_t numMpegAudioTypes = + sizeof(mpegAudioTypes) / sizeof(uint8_t); + + const char* typeName = "Unknown"; + bool foundType = false; + uint8_t type = 0; + const char *media_data_name; + + media_data_name = MP4GetTrackMediaDataName(mp4File, trackId); + + if (media_data_name == NULL) { + typeName = "Unknown - no media data name"; + } else if (strcasecmp(media_data_name, "samr") == 0) { + typeName = "AMR"; + foundType = true; + } else if (strcasecmp(media_data_name, "sawb") == 0) { + typeName = "AMR-WB"; + foundType = true; + } else if (strcasecmp(media_data_name, "mp4a") == 0) { + + type = MP4GetTrackEsdsObjectTypeId(mp4File, trackId); + switch (type) { + case MP4_INVALID_AUDIO_TYPE: + typeName = "AAC from .mov"; + foundType = true; + break; + case MP4_MPEG4_AUDIO_TYPE: { + + type = MP4GetTrackAudioMpeg4Type(mp4File, trackId); + if (type == MP4_MPEG4_INVALID_AUDIO_TYPE || + type > NUM_ELEMENTS_IN_ARRAY(mpeg4AudioNames) || + mpeg4AudioNames[type - 1] == NULL) { + typeName = "MPEG-4 Unknown Profile"; + } else { + typeName = mpeg4AudioNames[type - 1]; + foundType = true; + } + break; + } + // fall through + default: + for (uint8_t i = 0; i < numMpegAudioTypes; i++) { + if (type == mpegAudioTypes[i]) { + typeName = mpegAudioNames[i]; + foundType = true; + break; + } + } + } + } else { + typeName = media_data_name; + foundType = true; + } + + uint32_t timeScale = + MP4GetTrackTimeScale(mp4File, trackId); + + MP4Duration trackDuration = + MP4GetTrackDuration(mp4File, trackId); + + double msDuration = + double(MP4ConvertFromTrackDuration(mp4File, trackId, + trackDuration, MP4_MSECS_TIME_SCALE)); + + uint32_t avgBitRate = + MP4GetTrackBitRate(mp4File, trackId); + + char *sInfo = (char*)MP4Malloc(256); + + // type duration avgBitrate samplingFrequency + if (foundType) + snprintf(sInfo, 256, + "%u\taudio\t%s%s, %.3f secs, %u kbps, %u Hz\n", + trackId, + MP4IsIsmaCrypMediaTrack(mp4File, trackId) ? "enca - " : "", + typeName, + msDuration / 1000.0, + (avgBitRate + 500) / 1000, + timeScale); + else + snprintf(sInfo, 256, + "%u\taudio\t%s%s(%u), %.3f secs, %u kbps, %u Hz\n", + trackId, + MP4IsIsmaCrypMediaTrack(mp4File, trackId) ? "enca - " : "", + typeName, + type, + msDuration / 1000.0, + (avgBitRate + 500) / 1000, + timeScale); + + return sInfo; +} +static const struct { + uint8_t profile; + const char *name; +} VisualProfileToName[] = { + { MPEG4_SP_L1, "MPEG-4 Simple @ L1"}, + { MPEG4_SP_L2, "MPEG-4 Simple @ L2" }, + { MPEG4_SP_L3, "MPEG-4 Simple @ L3" }, + { MPEG4_SP_L0, "MPEG-4 Simple @ L0" }, + { MPEG4_SSP_L1, "MPEG-4 Simple Scalable @ L1"}, + { MPEG4_SSP_L2, "MPEG-4 Simple Scalable @ L2" }, + { MPEG4_CP_L1, "MPEG-4 Core @ L1"}, + { MPEG4_CP_L2, "MPEG-4 Core @ L2"}, + { MPEG4_MP_L2, "MPEG-4 Main @ L2"}, + { MPEG4_MP_L3, "MPEG-4 Main @ L3"}, + { MPEG4_MP_L4, "MPEG-4 Main @ L4"}, + { MPEG4_NBP_L2, "MPEG-4 N-bit @ L2"}, + { MPEG4_STP_L1, "MPEG-4 Scalable Texture @ L1"}, + { MPEG4_SFAP_L1, "MPEG-4 Simple Face Anim @ L1"}, + { MPEG4_SFAP_L2, "MPEG-4 Simple Face Anim @ L2"}, + { MPEG4_SFBAP_L1, "MPEG-4 Simple FBA @ L1"}, + { MPEG4_SFBAP_L2, "MPEG-4 Simple FBA @ L2"}, + { MPEG4_BATP_L1, "MPEG-4 Basic Anim Text @ L1"}, + { MPEG4_BATP_L2, "MPEG-4 Basic Anim Text @ L2"}, + { MPEG4_HP_L1, "MPEG-4 Hybrid @ L1"}, + { MPEG4_HP_L2, "MPEG-4 Hybrid @ L2"}, + { MPEG4_ARTSP_L1, "MPEG-4 Adv RT Simple @ L1"}, + { MPEG4_ARTSP_L2, "MPEG-4 Adv RT Simple @ L2"}, + { MPEG4_ARTSP_L3, "MPEG-4 Adv RT Simple @ L3"}, + { MPEG4_ARTSP_L4, "MPEG-4 Adv RT Simple @ L4"}, + { MPEG4_CSP_L1, "MPEG-4 Core Scalable @ L1"}, + { MPEG4_CSP_L2, "MPEG-4 Core Scalable @ L2"}, + { MPEG4_CSP_L3, "MPEG-4 Core Scalable @ L3"}, + { MPEG4_ACEP_L1, "MPEG-4 Adv Coding Efficieny @ L1"}, + { MPEG4_ACEP_L2, "MPEG-4 Adv Coding Efficieny @ L2"}, + { MPEG4_ACEP_L3, "MPEG-4 Adv Coding Efficieny @ L3"}, + { MPEG4_ACEP_L4, "MPEG-4 Adv Coding Efficieny @ L4"}, + { MPEG4_ACP_L1, "MPEG-4 Adv Core Profile @ L1"}, + { MPEG4_ACP_L2, "MPEG-4 Adv Core Profile @ L2"}, + { MPEG4_AST_L1, "MPEG-4 Adv Scalable Texture @ L1"}, + { MPEG4_AST_L2, "MPEG-4 Adv Scalable Texture @ L2"}, + { MPEG4_AST_L3, "MPEG-4 Adv Scalable Texture @ L3"}, + { MPEG4_S_STUDIO_P_L1, "MPEG-4 Simple Studio @ L1"}, + { MPEG4_S_STUDIO_P_L2, "MPEG-4 Simple Studio @ L2"}, + { MPEG4_S_STUDIO_P_L3, "MPEG-4 Simple Studio @ L3"}, + { MPEG4_S_STUDIO_P_L4, "MPEG-4 Simple Studio @ L4"}, + { MPEG4_C_STUDIO_P_L1, "MPEG-4 Core Studio @ L1"}, + { MPEG4_C_STUDIO_P_L2, "MPEG-4 Core Studio @ L2"}, + { MPEG4_C_STUDIO_P_L3, "MPEG-4 Core Studio @ L3"}, + { MPEG4_C_STUDIO_P_L4, "MPEG-4 Core Studio @ L4"}, + { MPEG4_ASP_L0, "MPEG-4 Adv Simple@L0"}, + { MPEG4_ASP_L1, "MPEG-4 Adv Simple@L1"}, + { MPEG4_ASP_L2, "MPEG-4 Adv Simple@L2"}, + { MPEG4_ASP_L3, "MPEG-4 Adv Simple@L3"}, + { MPEG4_ASP_L4, "MPEG-4 Adv Simple@L4"}, + { MPEG4_ASP_L5, "MPEG-4 Adv Simple@L5"}, + { MPEG4_ASP_L3B, "MPEG-4 Adv Simple@L3b"}, + { MPEG4_FGSP_L0, "MPEG-4 FGS @ L0" }, + { MPEG4_FGSP_L1, "MPEG-4 FGS @ L1" }, + { MPEG4_FGSP_L2, "MPEG-4 FGS @ L2" }, + { MPEG4_FGSP_L3, "MPEG-4 FGS @ L3" }, + { MPEG4_FGSP_L4, "MPEG-4 FGS @ L4" }, + { MPEG4_FGSP_L5, "MPEG-4 FGS @ L5" } +}; + +static const char *Mpeg4VisualProfileName (uint8_t visual_profile) +{ + size_t size = sizeof(VisualProfileToName) / sizeof(*VisualProfileToName); + + for (size_t ix = 0; ix < size; ix++) { + if (visual_profile == VisualProfileToName[ix].profile) { + return (VisualProfileToName[ix].name); + } + } + return (NULL); +} +static char* PrintVideoInfo( + MP4FileHandle mp4File, + MP4TrackId trackId) +{ + + static const uint8_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", + }; + uint8_t numMpegVideoTypes = + sizeof(mpegVideoTypes) / sizeof(uint8_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 (uint8_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 = + double(MP4ConvertFromTrackDuration(mp4File, trackId, + trackDuration, MP4_MSECS_TIME_SCALE)); + + uint32_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 + uint16_t width = MP4GetTrackVideoWidth(mp4File, trackId); + + uint16_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 char* PrintCntlInfo( + MP4FileHandle mp4File, + MP4TrackId trackId) +{ + const char *media_data_name = MP4GetTrackMediaDataName(mp4File, trackId); + const char *typeName = "Unknown"; + + if (media_data_name == NULL) { + typeName = "Unknown - no media data name"; + } else if (strcasecmp(media_data_name, "href") == 0) { + typeName = "ISMA Href"; + } else { + typeName = media_data_name; + } + + MP4Duration trackDuration = + MP4GetTrackDuration(mp4File, trackId); + + double msDuration = + double(MP4ConvertFromTrackDuration(mp4File, trackId, + trackDuration, MP4_MSECS_TIME_SCALE)); + char *sInfo = (char *)MP4Malloc(256); + + snprintf(sInfo, 256, + "%u\tcontrol\t%s, %.3f secs\n", + trackId, + typeName, + msDuration / 1000.0); + return sInfo; +} + + +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; +} + +static char* PrintTrackInfo( + MP4FileHandle mp4File, + MP4TrackId trackId) +{ + char* trackInfo = NULL; + + const char* trackType = + MP4GetTrackType(mp4File, trackId); + if (trackType == NULL) return NULL; + + if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE)) { + trackInfo = PrintAudioInfo(mp4File, trackId); + } else if (!strcmp(trackType, MP4_VIDEO_TRACK_TYPE)) { + trackInfo = PrintVideoInfo(mp4File, trackId); + } else if (!strcmp(trackType, MP4_HINT_TRACK_TYPE)) { + trackInfo = PrintHintInfo(mp4File, trackId); + } else if (strcmp(trackType, MP4_CNTL_TRACK_TYPE) == 0) { + trackInfo = PrintCntlInfo(mp4File, trackId); + } else { + trackInfo = (char*)MP4Malloc(256); + if (!strcmp(trackType, MP4_OD_TRACK_TYPE)) { + snprintf(trackInfo, 256, + "%u\tod\tObject Descriptors\n", + trackId); + } else if (!strcmp(trackType, MP4_SCENE_TRACK_TYPE)) { + snprintf(trackInfo, 256, + "%u\tscene\tBIFS\n", + trackId); + } else { + snprintf(trackInfo, 256, + "%u\t%s\n", + trackId, trackType); + } + } + + return trackInfo; +} + +/////////////////////////////////////////////////////////////////////////////// + +}} // namespace mp4v2::impl + +/////////////////////////////////////////////////////////////////////////////// + +using namespace mp4v2::impl; + +extern "C" +char* MP4Info( + MP4FileHandle mp4File, + MP4TrackId trackId ) +{ + char* info = NULL; + + if (MP4_IS_VALID_FILE_HANDLE(mp4File)) { + try { + if (trackId == MP4_INVALID_TRACK_ID) { + uint32_t buflen = 4 * 1024; + info = (char*)MP4Calloc(buflen); + + buflen -= snprintf(info, buflen, + "Track\tType\tInfo\n"); + + uint32_t numTracks = MP4GetNumberOfTracks(mp4File); + + for (uint32_t i = 0; i < numTracks; i++) { + trackId = MP4FindTrackId(mp4File, i); + char* trackInfo = PrintTrackInfo(mp4File, trackId); + strncat(info, trackInfo, buflen); + uint32_t newlen = (uint32_t)strlen(trackInfo); + if (newlen > buflen) buflen = 0; + else buflen -= newlen; + MP4Free(trackInfo); + } + } else { + info = PrintTrackInfo(mp4File, trackId); + } + } + catch (Exception* x) { + mp4v2::impl::log.errorf(*x); + delete x; + } + } + + return info; +} + +extern "C" +char* MP4FileInfo( + const char* fileName, + MP4TrackId trackId ) +{ + MP4FileHandle mp4File = MP4Read(fileName); + + if (!mp4File) { + return NULL; + } + + char* info = MP4Info(mp4File, trackId); + + MP4Close(mp4File); + + return info; // caller should free this +} |