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 = FindAtom(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 pAudioEsd->FindProperty("ESID", (MP4Property**)&pAudioEsdId); ASSERT(pAudioEsdId); pAudioEsdId->SetValue(audioTrackId); // SL config needs to change from 2 (file) to 1 (null) pAudioEsd->FindProperty("slConfigDescr.predefined", (MP4Property**)&pAudioSLConfigPredef); ASSERT(pAudioSLConfigPredef); pAudioSLConfigPredef->SetValue(0); 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 = FindAtom(MakeTrackName(videoTrackId, "mdia.minf.stbl.stsd.*.esds")); ASSERT(pEsdsAtom); pVideoEsd = (MP4DescriptorProperty*)(pEsdsAtom->GetProperty(2)); pVideoEsd->FindProperty("ESID", (MP4Property**)&pVideoEsdId); ASSERT(pVideoEsdId); pVideoEsdId->SetValue(videoTrackId); // SL config needs to change from 2 (file) to 1 (null) pVideoEsd->FindProperty("slConfigDescr.predefined", (MP4Property**)&pVideoSLConfigPredef); ASSERT(pVideoSLConfigPredef); pVideoSLConfigPredef->SetValue(0); pVideoEsd->FindProperty("slConfigDescr.useAccessUnitEndFlag", (MP4Property **)&pVideoAccessUnitEndFlag); oldVideoUnitEndFlagValue = pVideoAccessUnitEndFlag->GetValue(); pVideoAccessUnitEndFlag->SetValue(1); } CreateIsmaODUpdateCommandForStream( pAudioEsd, pVideoEsd, ppBytes, pNumBytes); VERBOSE_ISMA(GetVerbosity(), printf("After CreateImsaODUpdateCommandForStream len %llu =\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::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 = FindAtom("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; pIod->FindProperty("esIds", (MP4Property**)&pEsProperty); pEsProperty->SetTags(MP4ESDescrTag); MP4IntegerProperty* pSetProperty; MP4IntegerProperty* pSceneESID; MP4IntegerProperty* pOdESID; // OD MP4Descriptor* pOdEsd = pEsProperty->AddDescriptor(MP4ESDescrTag); pOdEsd->Generate(); pOdEsd->FindProperty("ESID", (MP4Property**)&pOdESID); // we set the OD ESID to a non-zero unique value pOdESID->SetValue(m_odTrackId); 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); char* urlBuf = (char*)MP4Malloc(strlen(odCmdBase64) + 64); sprintf(urlBuf, "data:application/mpeg4-od-au;base64,%s", odCmdBase64); MP4StringProperty* pUrlProperty; 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 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; pOdEsd->FindProperty("decConfigDescr.bufferSizeDB", (MP4Property**)&pBufferSizeProperty); ASSERT(pBufferSizeProperty); pBufferSizeProperty->SetValue(numBytes); // SL config needs to change from 2 (file) to 1 (null) pOdEsd->FindProperty("slConfigDescr.predefined", (MP4Property**)&pSetProperty); pSetProperty->SetValue(1); // Scene MP4Descriptor* pSceneEsd = pEsProperty->AddDescriptor(MP4ESDescrTag); pSceneEsd->Generate(); pSceneEsd->FindProperty("ESID", (MP4Property**)&pSceneESID); // we set the Scene ESID to a non-zero unique value pSceneESID->SetValue(sceneTrackId); 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); sprintf(urlBuf, "data:application/mpeg4-bifs-au;base64,%s", sceneCmdBase64); 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 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; pSceneEsd->FindProperty("decConfigDescr.bufferSizeDB", (MP4Property**)&pBufferSizeProperty); ASSERT(pBufferSizeProperty); pBufferSizeProperty->SetValue(numBytes); // SL config needs to change from 2 (file) to 1 (null) 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)); }