123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942 |
- /*
- * 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 - 2004. All Rights Reserved.
- *
- * 3GPP features implementation is based on 3GPP's TS26.234-v5.60,
- * and was contributed by Ximpo Group Ltd.
- *
- * Portions created by Ximpo Group Ltd. are
- * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved.
- *
- * Contributor(s):
- * Dave Mackie [email protected]
- * Alix Marchandise-Franquet [email protected]
- * Ximpo Group Ltd. [email protected]
- */
- #include "mp4common.h"
- static const u_int8_t BifsV2Config[3] = {
- 0x00, 0x00, 0x60 // IsCommandStream = 1, PixelMetric = 1
- };
- void MP4File::MakeIsmaCompliant(bool addIsmaComplianceSdp)
- {
- ProtectWriteOperation("MP4MakeIsmaCompliant");
- if (m_useIsma) {
- // already done
- return;
- }
- // find first audio and/or video tracks
- MP4TrackId audioTrackId = MP4_INVALID_TRACK_ID;
- try {
- audioTrackId = FindTrackId(0, MP4_AUDIO_TRACK_TYPE);
- }
- catch (MP4Error* e) {
- delete e;
- }
- MP4TrackId videoTrackId = MP4_INVALID_TRACK_ID;
- try {
- videoTrackId = FindTrackId(0, MP4_VIDEO_TRACK_TYPE);
- }
- catch (MP4Error* e) {
- delete e;
- }
- if (audioTrackId == MP4_INVALID_TRACK_ID &&
- videoTrackId == MP4_INVALID_TRACK_ID) return;
- const char *audio_media_data_name, *video_media_data_name;
- uint8_t videoProfile = 0xff;
- if (audioTrackId != MP4_INVALID_TRACK_ID) {
- audio_media_data_name = MP4GetTrackMediaDataName(this, audioTrackId);
- if (!(ATOMID(audio_media_data_name) == ATOMID("mp4a") ||
- ATOMID(audio_media_data_name) == ATOMID("enca"))) {
- VERBOSE_ERROR(m_verbosity,
- printf("MakeIsmaCompliant:can't make ISMA compliant when file contains an %s track\n", audio_media_data_name);
- );
- return;
- }
- }
- //
- // Note - might have to check for avc1 here...
- if (videoTrackId != MP4_INVALID_TRACK_ID) {
- video_media_data_name = MP4GetTrackMediaDataName(this, videoTrackId);
- if (!(ATOMID(video_media_data_name) == ATOMID("mp4v") ||
- ATOMID(video_media_data_name) == ATOMID("encv"))) {
- VERBOSE_ERROR(m_verbosity,
- printf("MakeIsmaCompliant:can't make ISMA compliant when file contains an %s track\n", video_media_data_name);
- );
- return;
- }
- uint32_t verb = GetVerbosity();
- SetVerbosity(verb & ~MP4_DETAILS_ERROR);
- videoProfile = MP4GetVideoProfileLevel(this, videoTrackId);
- SetVerbosity(verb);
- }
- m_useIsma = true;
- u_int64_t fileMsDuration = 0;
- fileMsDuration =
- ConvertFromMovieDuration(GetDuration(), MP4_MSECS_TIME_SCALE);
- // delete any existing OD track
- if (m_odTrackId != MP4_INVALID_TRACK_ID) {
- DeleteTrack(m_odTrackId);
- }
- if (m_pRootAtom->FindAtomMP4("moov.iods") == NULL) {
- (void)AddChildAtom("moov", "iods");
- }
- (void)AddODTrack();
- SetODProfileLevel(0xFF);
- if (audioTrackId != MP4_INVALID_TRACK_ID) {
- AddTrackToOd(audioTrackId);
- MP4SetAudioProfileLevel(this, 0xf);
- }
- if (videoTrackId != MP4_INVALID_TRACK_ID) {
- AddTrackToOd(videoTrackId);
- MP4SetVideoProfileLevel(this, videoProfile);
- }
- // delete any existing scene track
- MP4TrackId sceneTrackId = MP4_INVALID_TRACK_ID;
- try {
- sceneTrackId = FindTrackId(0, MP4_SCENE_TRACK_TYPE);
- }
- catch (MP4Error *e) {
- delete e;
- }
- if (sceneTrackId != MP4_INVALID_TRACK_ID) {
- DeleteTrack(sceneTrackId);
- }
- // add scene track
- sceneTrackId = AddSceneTrack();
- SetSceneProfileLevel(0xFF);
- SetGraphicsProfileLevel(0xFF);
- SetTrackIntegerProperty(sceneTrackId,
- "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr.objectTypeId",
- MP4SystemsV2ObjectType);
-
- SetTrackESConfiguration(sceneTrackId,
- BifsV2Config, sizeof(BifsV2Config));
- u_int8_t* pBytes = NULL;
- u_int64_t numBytes = 0;
- // write OD Update Command
- CreateIsmaODUpdateCommandFromFileForFile(
- m_odTrackId,
- audioTrackId,
- videoTrackId,
- &pBytes,
- &numBytes);
- WriteSample(m_odTrackId, pBytes, numBytes, fileMsDuration);
- MP4Free(pBytes);
- pBytes = NULL;
- // write BIFS Scene Replace Command
- CreateIsmaSceneCommand(
- MP4_IS_VALID_TRACK_ID(audioTrackId),
- MP4_IS_VALID_TRACK_ID(videoTrackId),
- &pBytes,
- &numBytes);
- WriteSample(sceneTrackId, pBytes, numBytes, fileMsDuration);
- MP4Free(pBytes);
- pBytes = NULL;
- // add session level sdp
- CreateIsmaIodFromFile(
- m_odTrackId,
- sceneTrackId,
- audioTrackId,
- videoTrackId,
- &pBytes,
- &numBytes);
- char* iodBase64 = MP4ToBase64(pBytes, numBytes);
- uint sdpBufLen = (uint)strlen(iodBase64) + 256;
- uint used;
- char* sdpBuf = (char*)MP4Calloc(sdpBufLen);
- if (addIsmaComplianceSdp) {
- strncpy(sdpBuf, "a=isma-compliance:1,1.0,1\015\012", sdpBufLen);
- }
- used = (uint)strlen(sdpBuf);
- sdpBufLen -= used;
- snprintf(&sdpBuf[used], sdpBufLen,
- "a=mpeg4-iod: \042data:application/mpeg4-iod;base64,%s\042\015\012",
- iodBase64);
- SetSessionSdp(sdpBuf);
- VERBOSE_ISMA(GetVerbosity(),
- printf("IOD SDP = %s\n", sdpBuf));
- MP4Free(iodBase64);
- iodBase64 = NULL;
- MP4Free(pBytes);
- pBytes = NULL;
- MP4Free(sdpBuf);
- sdpBuf = NULL;
- }
- static void CloneIntegerProperty(
- MP4Descriptor* pDest,
- MP4DescriptorProperty* pSrc,
- const char* name)
- {
- MP4IntegerProperty* pGetProperty;
- MP4IntegerProperty* pSetProperty;
- if (!pSrc->FindProperty(name, (MP4Property**)&pGetProperty)) return;
- if (!pDest->FindProperty(name, (MP4Property**)&pSetProperty)) return;
- pSetProperty->SetValue(pGetProperty->GetValue());
- }
- void MP4File::CreateIsmaIodFromFile(
- MP4TrackId odTrackId,
- MP4TrackId sceneTrackId,
- MP4TrackId audioTrackId,
- MP4TrackId videoTrackId,
- u_int8_t** ppBytes,
- u_int64_t* pNumBytes)
- {
- MP4Descriptor* pIod = new MP4IODescriptor();
- pIod->SetTag(MP4IODescrTag);
- pIod->Generate();
- MP4Atom* pIodsAtom = FindAtomMP4File("moov.iods");
- ASSERT(pIodsAtom);
- MP4DescriptorProperty* pSrcIod =
- (MP4DescriptorProperty*)pIodsAtom->GetProperty(2);
- CloneIntegerProperty(pIod, pSrcIod, "objectDescriptorId");
- CloneIntegerProperty(pIod, pSrcIod, "ODProfileLevelId");
- CloneIntegerProperty(pIod, pSrcIod, "sceneProfileLevelId");
- CloneIntegerProperty(pIod, pSrcIod, "audioProfileLevelId");
- CloneIntegerProperty(pIod, pSrcIod, "visualProfileLevelId");
- CloneIntegerProperty(pIod, pSrcIod, "graphicsProfileLevelId");
- // mutate esIds from MP4ESIDIncDescrTag to MP4ESDescrTag
- MP4DescriptorProperty* pEsProperty;
- if (!pIod->FindProperty("esIds", (MP4Property**)&pEsProperty)) return;
- pEsProperty->SetTags(MP4ESDescrTag);
- MP4IntegerProperty* pSetProperty;
- MP4IntegerProperty* pSceneESID;
- MP4IntegerProperty* pOdESID;
- // OD
- MP4Descriptor* pOdEsd =
- pEsProperty->AddDescriptor(MP4ESDescrTag);
- pOdEsd->Generate();
- if (!pOdEsd->FindProperty("ESID", (MP4Property**)&pOdESID)) return;
- // we set the OD ESID to a non-zero unique value
- pOdESID->SetValue(m_odTrackId);
- if (pOdEsd->FindProperty("URLFlag",
- (MP4Property**)&pSetProperty))
- pSetProperty->SetValue(1);
- u_int8_t* pBytes;
- u_int64_t numBytes;
- CreateIsmaODUpdateCommandFromFileForStream(
- audioTrackId,
- videoTrackId,
- &pBytes,
- &numBytes);
- VERBOSE_ISMA(GetVerbosity(),
- printf("OD data =\n"); MP4HexDump(pBytes, numBytes));
- char* odCmdBase64 = MP4ToBase64(pBytes, numBytes);
- uint urlBufLen = (uint)strlen(odCmdBase64) + 64;
- char* urlBuf = (char*)MP4Malloc(urlBufLen);
- snprintf(urlBuf, urlBufLen,
- "data:application/mpeg4-od-au;base64,%s",
- odCmdBase64);
- MP4StringProperty* pUrlProperty;
- if (pOdEsd->FindProperty("URL",
- (MP4Property**)&pUrlProperty))
- pUrlProperty->SetValue(urlBuf);
- VERBOSE_ISMA(GetVerbosity(),
- printf("OD data URL = \042%s\042\n", urlBuf));
- MP4Free(odCmdBase64);
- odCmdBase64 = NULL;
- MP4Free(pBytes);
- pBytes = NULL;
- MP4Free(urlBuf);
- urlBuf = NULL;
- MP4DescriptorProperty* pSrcDcd = NULL;
- // HACK temporarily point to scene decoder config
- (void)FindProperty(MakeTrackName(odTrackId,
- "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr"),
- (MP4Property**)&pSrcDcd);
- ASSERT(pSrcDcd);
- MP4Property* pOrgOdEsdProperty =
- pOdEsd->GetProperty(8);
- pOdEsd->SetProperty(8, pSrcDcd);
- // bufferSizeDB needs to be set appropriately
- MP4BitfieldProperty* pBufferSizeProperty = NULL;
- if (pOdEsd->FindProperty("decConfigDescr.bufferSizeDB",
- (MP4Property**)&pBufferSizeProperty)) {
- ASSERT(pBufferSizeProperty);
- pBufferSizeProperty->SetValue(numBytes);
- }
- // SL config needs to change from 2 (file) to 1 (null)
- if (pOdEsd->FindProperty("slConfigDescr.predefined",
- (MP4Property**)&pSetProperty))
- pSetProperty->SetValue(1);
- // Scene
- MP4Descriptor* pSceneEsd =
- pEsProperty->AddDescriptor(MP4ESDescrTag);
- pSceneEsd->Generate();
- if (pSceneEsd->FindProperty("ESID",
- (MP4Property**)&pSceneESID)) {
- // we set the Scene ESID to a non-zero unique value
- pSceneESID->SetValue(sceneTrackId);
- }
- if (pSceneEsd->FindProperty("URLFlag",
- (MP4Property**)&pSetProperty))
- pSetProperty->SetValue(1);
- CreateIsmaSceneCommand(
- MP4_IS_VALID_TRACK_ID(audioTrackId),
- MP4_IS_VALID_TRACK_ID(videoTrackId),
- &pBytes,
- &numBytes);
- VERBOSE_ISMA(GetVerbosity(),
- printf("Scene data =\n"); MP4HexDump(pBytes, numBytes));
- char *sceneCmdBase64 = MP4ToBase64(pBytes, numBytes);
- urlBuf = (char*)MP4Malloc(strlen(sceneCmdBase64) + 64);
- snprintf(urlBuf, strlen(sceneCmdBase64) + 64,
- "data:application/mpeg4-bifs-au;base64,%s",
- sceneCmdBase64);
- if (pSceneEsd->FindProperty("URL",
- (MP4Property**)&pUrlProperty))
- pUrlProperty->SetValue(urlBuf);
- VERBOSE_ISMA(GetVerbosity(),
- printf("Scene data URL = \042%s\042\n", urlBuf));
- MP4Free(sceneCmdBase64);
- sceneCmdBase64 = NULL;
- MP4Free(urlBuf);
- urlBuf = NULL;
- MP4Free(pBytes);
- pBytes = NULL;
- // HACK temporarily point to scene decoder config
- ASSERT(FindProperty(MakeTrackName(sceneTrackId,
- "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr"),
- (MP4Property**)&pSrcDcd));
- ASSERT(pSrcDcd);
- MP4Property* pOrgSceneEsdProperty =
- pSceneEsd->GetProperty(8);
- pSceneEsd->SetProperty(8, pSrcDcd);
- // bufferSizeDB needs to be set
- pBufferSizeProperty = NULL;
- if (pSceneEsd->FindProperty("decConfigDescr.bufferSizeDB",
- (MP4Property**)&pBufferSizeProperty)) {
- ASSERT(pBufferSizeProperty);
- pBufferSizeProperty->SetValue(numBytes);
- }
- // SL config needs to change from 2 (file) to 1 (null)
- if (pSceneEsd->FindProperty("slConfigDescr.predefined",
- (MP4Property**)&pSetProperty))
- pSetProperty->SetValue(1);
- // finally get the whole thing written to a memory
- pIod->WriteToMemory(this, ppBytes, pNumBytes);
- // now carefully replace esd properties before destroying
- pOdEsd->SetProperty(8, pOrgOdEsdProperty);
- pSceneEsd->SetProperty(8, pOrgSceneEsdProperty);
- pSceneESID->SetValue(0); // restore 0 value
- pOdESID->SetValue(0);
- delete pIod;
- VERBOSE_ISMA(GetVerbosity(),
- printf("IOD data =\n"); MP4HexDump(*ppBytes, *pNumBytes));
- }
- void MP4File::CreateIsmaIodFromParams(
- u_int8_t videoProfile,
- u_int32_t videoBitrate,
- u_int8_t* videoConfig,
- u_int32_t videoConfigLength,
- u_int8_t audioProfile,
- u_int32_t audioBitrate,
- u_int8_t* audioConfig,
- u_int32_t audioConfigLength,
- u_int8_t** ppIodBytes,
- u_int64_t* pIodNumBytes)
- {
- MP4IntegerProperty* pInt;
- u_int8_t* pBytes = NULL;
- u_int64_t numBytes;
- // Create the IOD
- MP4Descriptor* pIod = new MP4IODescriptor();
- pIod->SetTag(MP4IODescrTag);
- pIod->Generate();
-
- // Set audio and video profileLevels
- if (pIod->FindProperty("audioProfileLevelId",
- (MP4Property**)&pInt))
- pInt->SetValue(audioProfile);
- if (pIod->FindProperty("visualProfileLevelId",
- (MP4Property**)&pInt))
- pInt->SetValue(videoProfile);
- // Mutate esIds from MP4ESIDIncDescrTag to MP4ESDescrTag
- MP4DescriptorProperty* pEsProperty;
- if (!pIod->FindProperty("esIds", (MP4Property**)&pEsProperty)) return;
- pEsProperty->SetTags(MP4ESDescrTag);
- // Add ES Descriptors
- // Scene
- CreateIsmaSceneCommand(
- (audioProfile != 0xFF),
- (videoProfile != 0xFF),
- &pBytes,
- &numBytes);
- VERBOSE_ISMA(GetVerbosity(),
- printf("Scene data =\n"); MP4HexDump(pBytes, numBytes));
- char* sceneCmdBase64 = MP4ToBase64(pBytes, numBytes);
- char* urlBuf =
- (char*)MP4Malloc(strlen(sceneCmdBase64) + 64);
- snprintf(urlBuf, strlen(sceneCmdBase64) + 64,
- "data:application/mpeg4-bifs-au;base64,%s",
- sceneCmdBase64);
-
- VERBOSE_ISMA(GetVerbosity(),
- printf("Scene data URL = \042%s\042\n", urlBuf));
-
- /* MP4Descriptor* pSceneEsd = */
- CreateESD(
- pEsProperty,
- 201, // esid
- MP4SystemsV2ObjectType,
- MP4SceneDescriptionStreamType,
- numBytes, // bufferSize
- numBytes * 8, // bitrate
- BifsV2Config,
- sizeof(BifsV2Config),
- urlBuf);
- MP4Free(urlBuf);
- urlBuf = NULL;
- MP4Free(sceneCmdBase64);
- sceneCmdBase64 = NULL;
- MP4Free(pBytes);
- pBytes = NULL;
- // OD
-
- // Video
- MP4DescriptorProperty* pVideoEsdProperty =
- new MP4DescriptorProperty();
- pVideoEsdProperty->SetTags(MP4ESDescrTag);
- /* MP4Descriptor* pVideoEsd = */
- CreateESD(
- pVideoEsdProperty,
- 20, // esid
- MP4_MPEG4_VIDEO_TYPE,
- MP4VisualStreamType,
- videoBitrate / 8, // bufferSize
- videoBitrate,
- videoConfig,
- videoConfigLength,
- NULL);
- // Audio
- MP4DescriptorProperty* pAudioEsdProperty =
- new MP4DescriptorProperty();
- pAudioEsdProperty->SetTags(MP4ESDescrTag);
-
- /* MP4Descriptor* pAudioEsd = */
- CreateESD(
- pAudioEsdProperty,
- 10, // esid
- MP4_MPEG4_AUDIO_TYPE,
- MP4AudioStreamType,
- audioBitrate / 8, // bufferSize
- audioBitrate,
- audioConfig,
- audioConfigLength,
- NULL);
-
- CreateIsmaODUpdateCommandForStream(
- pAudioEsdProperty,
- pVideoEsdProperty,
- &pBytes,
- &numBytes);
- // cleanup temporary descriptor properties
- delete pAudioEsdProperty;
- delete pVideoEsdProperty;
- VERBOSE_ISMA(GetVerbosity(),
- printf("OD data = "U64" bytes\n", numBytes); MP4HexDump(pBytes, numBytes));
- char* odCmdBase64 = MP4ToBase64(pBytes, numBytes);
- urlBuf = (char*)MP4Malloc(strlen(odCmdBase64) + 64);
- if (urlBuf != NULL) {
- snprintf(urlBuf, strlen(odCmdBase64) + 64,
- "data:application/mpeg4-od-au;base64,%s",
- odCmdBase64);
- VERBOSE_ISMA(GetVerbosity(),
- printf("OD data URL = \042%s\042\n", urlBuf));
- /* MP4Descriptor* pOdEsd = */
- CreateESD(
- pEsProperty,
- 101,
- MP4SystemsV1ObjectType,
- MP4ObjectDescriptionStreamType,
- numBytes, // bufferSize
- numBytes * 8, // bitrate
- NULL, // config
- 0, // configLength
- urlBuf);
- MP4Free(urlBuf);
- urlBuf = NULL;
- }
- MP4Free(odCmdBase64);
- odCmdBase64 = NULL;
- MP4Free(pBytes);
- pBytes = NULL;
- // finally get the whole thing written to a memory
- pIod->WriteToMemory(this, ppIodBytes, pIodNumBytes);
- delete pIod;
- VERBOSE_ISMA(GetVerbosity(),
- printf("IOD data =\n"); MP4HexDump(*ppIodBytes, *pIodNumBytes));
- }
- void MP4File::CreateESD(
- MP4DescriptorProperty* pEsProperty,
- u_int32_t esid,
- u_int8_t objectType,
- u_int8_t streamType,
- u_int32_t bufferSize,
- u_int32_t bitrate,
- const u_int8_t* pConfig,
- u_int32_t configLength,
- char* url)
- {
- MP4IntegerProperty* pInt;
- MP4StringProperty* pString;
- MP4BytesProperty* pBytes;
- MP4BitfieldProperty* pBits;
- MP4Descriptor* pEsd =
- pEsProperty->AddDescriptor(MP4ESDescrTag);
- pEsd->Generate();
- if (pEsd->FindProperty("ESID",
- (MP4Property**)&pInt))
- pInt->SetValue(esid);
- if (pEsd->FindProperty("decConfigDescr.objectTypeId",
- (MP4Property**)&pInt))
- pInt->SetValue(objectType);
- if (pEsd->FindProperty("decConfigDescr.streamType",
- (MP4Property**)&pInt))
- pInt->SetValue(streamType);
- if (pEsd->FindProperty("decConfigDescr.bufferSizeDB",
- (MP4Property**)&pInt))
- pInt->SetValue(bufferSize);
- if (pEsd->FindProperty("decConfigDescr.maxBitrate",
- (MP4Property**)&pInt))
- pInt->SetValue(bitrate);
- if (pEsd->FindProperty("decConfigDescr.avgBitrate",
- (MP4Property**)&pInt))
- pInt->SetValue(bitrate);
-
- MP4DescriptorProperty* pConfigDescrProperty;
- if (pEsd->FindProperty("decConfigDescr.decSpecificInfo",
- (MP4Property**)&pConfigDescrProperty)) {
- MP4Descriptor* pConfigDescr =
- pConfigDescrProperty->AddDescriptor(MP4DecSpecificDescrTag);
- pConfigDescr->Generate();
- if (pConfigDescrProperty->FindProperty("decSpecificInfo[0].info",
- (MP4Property**)&pBytes))
- pBytes->SetValue(pConfig, configLength);
- }
- if (pEsd->FindProperty("slConfigDescr.predefined",
- (MP4Property**)&pInt))
- // changed 12/5/02 from plugfest to value 0
- pInt->SetValue(0);
- if (pEsd->FindProperty("slConfig.useAccessUnitEndFlag",
- (MP4Property **)&pBits))
- pBits->SetValue(1);
- if (url) {
- if (pEsd->FindProperty("URLFlag",
- (MP4Property**)&pInt))
- pInt->SetValue(1);
- if (pEsd->FindProperty("URL",
- (MP4Property**)&pString))
- pString->SetValue(url);
- }
- //return pEsd;
- }
- void MP4File::CreateIsmaODUpdateCommandFromFileForFile(
- MP4TrackId odTrackId,
- MP4TrackId audioTrackId,
- MP4TrackId videoTrackId,
- u_int8_t** ppBytes,
- u_int64_t* pNumBytes)
- {
- MP4Descriptor* pCommand = CreateODCommand(MP4ODUpdateODCommandTag);
- pCommand->Generate();
- for (u_int8_t i = 0; i < 2; i++) {
- MP4TrackId trackId;
- u_int16_t odId;
- if (i == 0) {
- trackId = audioTrackId;
- odId = 10;
- } else {
- trackId = videoTrackId;
- odId = 20;
- }
- if (trackId == MP4_INVALID_TRACK_ID) {
- continue;
- }
- MP4DescriptorProperty* pOdDescrProperty =
- (MP4DescriptorProperty*)(pCommand->GetProperty(0));
- pOdDescrProperty->SetTags(MP4FileODescrTag);
- MP4Descriptor* pOd =
- pOdDescrProperty->AddDescriptor(MP4FileODescrTag);
- pOd->Generate();
- MP4BitfieldProperty* pOdIdProperty = NULL;
- if (pOd->FindProperty("objectDescriptorId",
- (MP4Property**)&pOdIdProperty))
- pOdIdProperty->SetValue(odId);
- MP4DescriptorProperty* pEsIdsDescriptorProperty = NULL;
- ASSERT(pOd->FindProperty("esIds",
- (MP4Property**)&pEsIdsDescriptorProperty));
- ASSERT(pEsIdsDescriptorProperty);
- pEsIdsDescriptorProperty->SetTags(MP4ESIDRefDescrTag);
- MP4Descriptor *pRefDescriptor =
- pEsIdsDescriptorProperty->AddDescriptor(MP4ESIDRefDescrTag);
- pRefDescriptor->Generate();
- MP4Integer16Property* pRefIndexProperty = NULL;
- ASSERT(pRefDescriptor->FindProperty("refIndex",
- (MP4Property**)&pRefIndexProperty));
- ASSERT(pRefIndexProperty);
- u_int32_t mpodIndex = FindTrackReference(
- MakeTrackName(odTrackId, "tref.mpod"), trackId);
- ASSERT(mpodIndex != 0);
- pRefIndexProperty->SetValue(mpodIndex);
- }
- pCommand->WriteToMemory(this, ppBytes, pNumBytes);
- delete pCommand;
- }
- void MP4File::CreateIsmaODUpdateCommandFromFileForStream(
- MP4TrackId audioTrackId,
- MP4TrackId videoTrackId,
- u_int8_t** ppBytes,
- u_int64_t* pNumBytes)
- {
- MP4DescriptorProperty* pAudioEsd = NULL;
- MP4Integer8Property* pAudioSLConfigPredef = NULL;
- MP4BitfieldProperty* pAudioAccessUnitEndFlag = NULL;
- int oldAudioUnitEndFlagValue = 0;
- MP4DescriptorProperty* pVideoEsd = NULL;
- MP4Integer8Property* pVideoSLConfigPredef = NULL;
- MP4BitfieldProperty* pVideoAccessUnitEndFlag = NULL;
- int oldVideoUnitEndFlagValue = 0;
- MP4IntegerProperty* pAudioEsdId = NULL;
- MP4IntegerProperty* pVideoEsdId = NULL;
- if (audioTrackId != MP4_INVALID_TRACK_ID) {
- // changed mp4a to * to handle enca case
- MP4Atom* pEsdsAtom =
- FindAtomMP4File(MakeTrackName(audioTrackId,
- "mdia.minf.stbl.stsd.*.esds"));
- ASSERT(pEsdsAtom);
- pAudioEsd = (MP4DescriptorProperty*)(pEsdsAtom->GetProperty(2));
- // ESID is 0 for file, stream needs to be non-ze
- ASSERT(pAudioEsd->FindProperty("ESID",
- (MP4Property**)&pAudioEsdId));
- ASSERT(pAudioEsdId);
- pAudioEsdId->SetValue(audioTrackId);
- // SL config needs to change from 2 (file) to 1 (null)
- if (pAudioEsd->FindProperty("slConfigDescr.predefined",
- (MP4Property**)&pAudioSLConfigPredef)) {
- ASSERT(pAudioSLConfigPredef);
- pAudioSLConfigPredef->SetValue(0);
- }
- if (pAudioEsd->FindProperty("slConfigDescr.useAccessUnitEndFlag",
- (MP4Property **)&pAudioAccessUnitEndFlag)) {
- oldAudioUnitEndFlagValue =
- pAudioAccessUnitEndFlag->GetValue();
- pAudioAccessUnitEndFlag->SetValue(1);
- }
- }
- if (videoTrackId != MP4_INVALID_TRACK_ID) {
- // changed mp4v to * to handle encv case
- MP4Atom* pEsdsAtom =
- FindAtomMP4File(MakeTrackName(videoTrackId,
- "mdia.minf.stbl.stsd.*.esds"));
- ASSERT(pEsdsAtom);
- pVideoEsd = (MP4DescriptorProperty*)(pEsdsAtom->GetProperty(2));
- ASSERT(pVideoEsd->FindProperty("ESID",
- (MP4Property**)&pVideoEsdId));
- ASSERT(pVideoEsdId);
- pVideoEsdId->SetValue(videoTrackId);
- // SL config needs to change from 2 (file) to 1 (null)
- ASSERT(pVideoEsd->FindProperty("slConfigDescr.predefined",
- (MP4Property **)&pVideoSLConfigPredef));
- ASSERT(pVideoSLConfigPredef);
- pVideoSLConfigPredef->SetValue(0);
- if (pVideoEsd->FindProperty("slConfigDescr.useAccessUnitEndFlag",
- (MP4Property **)&pVideoAccessUnitEndFlag)) {
- oldVideoUnitEndFlagValue =
- pVideoAccessUnitEndFlag->GetValue();
- pVideoAccessUnitEndFlag->SetValue(1);
- }
- }
- CreateIsmaODUpdateCommandForStream(
- pAudioEsd, pVideoEsd, ppBytes, pNumBytes);
- VERBOSE_ISMA(GetVerbosity(),
- printf("After CreateImsaODUpdateCommandForStream len "U64" =\n", *pNumBytes); MP4HexDump(*ppBytes, *pNumBytes));
- // return SL config values to 2 (file)
- // return ESID values to 0
- if (pAudioSLConfigPredef) {
- pAudioSLConfigPredef->SetValue(2);
- }
- if (pAudioEsdId) {
- pAudioEsdId->SetValue(0);
- }
- if (pAudioAccessUnitEndFlag) {
- pAudioAccessUnitEndFlag->SetValue(oldAudioUnitEndFlagValue );
- }
- if (pVideoEsdId) {
- pVideoEsdId->SetValue(0);
- }
- if (pVideoSLConfigPredef) {
- pVideoSLConfigPredef->SetValue(2);
- }
- if (pVideoAccessUnitEndFlag) {
- pVideoAccessUnitEndFlag->SetValue(oldVideoUnitEndFlagValue );
- }
- }
- void MP4File::CreateIsmaODUpdateCommandForStream(
- MP4DescriptorProperty* pAudioEsdProperty,
- MP4DescriptorProperty* pVideoEsdProperty,
- u_int8_t** ppBytes,
- u_int64_t* pNumBytes)
- {
- MP4Descriptor* pAudioOd = NULL;
- MP4Descriptor* pVideoOd = NULL;
- MP4Descriptor* pCommand =
- CreateODCommand(MP4ODUpdateODCommandTag);
- pCommand->Generate();
- for (u_int8_t i = 0; i < 2; i++) {
- u_int16_t odId;
- MP4DescriptorProperty* pEsdProperty = NULL;
- if (i == 0) {
- odId = 10;
- pEsdProperty = pAudioEsdProperty;
- } else {
- odId = 20;
- pEsdProperty = pVideoEsdProperty;
- }
- if (pEsdProperty == NULL) {
- continue;
- }
- MP4DescriptorProperty* pOdDescrProperty =
- (MP4DescriptorProperty*)(pCommand->GetProperty(0));
- pOdDescrProperty->SetTags(MP4ODescrTag);
- MP4Descriptor* pOd =
- pOdDescrProperty->AddDescriptor(MP4ODescrTag);
- pOd->Generate();
- if (i == 0) {
- pAudioOd = pOd;
- } else {
- pVideoOd = pOd;
- }
- MP4BitfieldProperty* pOdIdProperty = NULL;
- if (pOd->FindProperty("objectDescriptorId",
- (MP4Property**)&pOdIdProperty)) {
- pOdIdProperty->SetValue(odId);
- }
- delete (MP4DescriptorProperty*)pOd->GetProperty(4);
- pOd->SetProperty(4, pEsdProperty);
- }
- // serialize OD command
- pCommand->WriteToMemory(this, ppBytes, pNumBytes);
- // detach from esd descriptor params
- if (pAudioOd) {
- pAudioOd->SetProperty(4, NULL);
- }
- if (pVideoOd) {
- pVideoOd->SetProperty(4, NULL);
- }
- // then destroy
- delete pCommand;
- }
- void MP4File::CreateIsmaSceneCommand(
- bool hasAudio,
- bool hasVideo,
- u_int8_t** ppBytes,
- u_int64_t* pNumBytes)
- {
- // from ISMA 1.0 Tech Spec Appendix E
- static const u_int8_t bifsAudioOnly[] = {
- 0xC0, 0x10, 0x12,
- 0x81, 0x30, 0x2A, 0x05, 0x6D, 0xC0
- };
- static const u_int8_t bifsVideoOnly[] = {
- 0xC0, 0x10, 0x12,
- 0x61, 0x04,
- 0x1F, 0xC0, 0x00, 0x00,
- 0x1F, 0xC0, 0x00, 0x00,
- 0x44, 0x28, 0x22, 0x82, 0x9F, 0x80
- };
- static const u_int8_t bifsAudioVideo[] = {
- 0xC0, 0x10, 0x12,
- 0x81, 0x30, 0x2A, 0x05, 0x6D, 0x26,
- 0x10, 0x41, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00,
- 0x04, 0x42, 0x82, 0x28, 0x29, 0xF8
- };
- if (hasAudio && hasVideo) {
- *pNumBytes = sizeof(bifsAudioVideo);
- *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes);
- memcpy(*ppBytes, bifsAudioVideo, sizeof(bifsAudioVideo));
- } else if (hasAudio) {
- *pNumBytes = sizeof(bifsAudioOnly);
- *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes);
- memcpy(*ppBytes, bifsAudioOnly, sizeof(bifsAudioOnly));
- } else if (hasVideo) {
- *pNumBytes = sizeof(bifsVideoOnly);
- *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes);
- memcpy(*ppBytes, bifsVideoOnly, sizeof(bifsVideoOnly));
- } else {
- *pNumBytes = 0;
- *ppBytes = NULL;
- }
- }
|