isma.cpp
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:20k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is MPEG4IP.
  13.  * 
  14.  * The Initial Developer of the Original Code is Cisco Systems Inc.
  15.  * Portions created by Cisco Systems Inc. are
  16.  * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  * Dave Mackie dmackie@cisco.com
  20.  */
  21. #include "mp4common.h"
  22. static u_int8_t BifsV2Config[3] = {
  23. 0x00, 0x00, 0x40 // IsCommandStream
  24. };
  25. void MP4File::MakeIsmaCompliant(bool addIsmaComplianceSdp)
  26. {
  27. ProtectWriteOperation("MP4MakeIsmaCompliant");
  28. if (m_useIsma) {
  29. // already done
  30. return;
  31. }
  32. m_useIsma = true;
  33. // find first audio and/or video tracks
  34. MP4TrackId audioTrackId = MP4_INVALID_TRACK_ID;
  35. try {
  36. audioTrackId = FindTrackId(0, MP4_AUDIO_TRACK_TYPE);
  37. }
  38. catch (MP4Error* e) {
  39. delete e;
  40. }
  41. MP4TrackId videoTrackId = MP4_INVALID_TRACK_ID;
  42. try {
  43. videoTrackId = FindTrackId(0, MP4_VIDEO_TRACK_TYPE);
  44. }
  45. catch (MP4Error* e) {
  46. delete e;
  47. }
  48. u_int64_t fileMsDuration =
  49. ConvertFromMovieDuration(GetDuration(), MP4_MSECS_TIME_SCALE);
  50. // delete any existing OD track
  51. if (m_odTrackId != MP4_INVALID_TRACK_ID) {
  52. DeleteTrack(m_odTrackId);
  53. }
  54. AddODTrack();
  55. SetODProfileLevel(0xFF);
  56. if (audioTrackId != MP4_INVALID_TRACK_ID) {
  57. AddTrackToOd(audioTrackId);
  58. }
  59. if (videoTrackId != MP4_INVALID_TRACK_ID) {
  60. AddTrackToOd(videoTrackId);
  61. }
  62. // delete any existing scene track
  63. MP4TrackId sceneTrackId = MP4_INVALID_TRACK_ID;
  64. try {
  65. sceneTrackId = FindTrackId(0, MP4_SCENE_TRACK_TYPE);
  66. }
  67. catch (MP4Error *e) {
  68. delete e;
  69. }
  70. if (sceneTrackId != MP4_INVALID_TRACK_ID) {
  71. DeleteTrack(sceneTrackId);
  72. }
  73. // add scene track
  74. sceneTrackId = AddSceneTrack();
  75. SetSceneProfileLevel(0xFF);
  76. SetGraphicsProfileLevel(0xFF);
  77. SetTrackIntegerProperty(sceneTrackId, 
  78. "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr.objectTypeId", 
  79. MP4SystemsV2ObjectType);
  80. SetTrackESConfiguration(sceneTrackId, 
  81. BifsV2Config, sizeof(BifsV2Config));
  82. u_int8_t* pBytes = NULL;
  83. u_int64_t numBytes = 0;
  84. // write OD Update Command
  85. CreateIsmaODUpdateCommandFromFileForFile(
  86. m_odTrackId, 
  87. audioTrackId, 
  88. videoTrackId,
  89. &pBytes, 
  90. &numBytes);
  91. WriteSample(m_odTrackId, pBytes, numBytes, fileMsDuration);
  92. MP4Free(pBytes);
  93. pBytes = NULL;
  94. // write BIFS Scene Replace Command
  95. CreateIsmaSceneCommand(
  96. MP4_IS_VALID_TRACK_ID(audioTrackId), 
  97. MP4_IS_VALID_TRACK_ID(videoTrackId),
  98. &pBytes, 
  99. &numBytes);
  100. WriteSample(sceneTrackId, pBytes, numBytes, fileMsDuration);
  101. MP4Free(pBytes);
  102. pBytes = NULL;
  103. // add session level sdp 
  104. CreateIsmaIodFromFile(
  105. m_odTrackId, 
  106. sceneTrackId, 
  107. audioTrackId, 
  108. videoTrackId,
  109. &pBytes, 
  110. &numBytes);
  111. char* iodBase64 = MP4ToBase64(pBytes, numBytes);
  112. char* sdpBuf = (char*)MP4Calloc(strlen(iodBase64) + 256);
  113. if (addIsmaComplianceSdp) {
  114. strcpy(sdpBuf, "a=isma-compliance:1,1.0,11512");
  115. }
  116. sprintf(&sdpBuf[strlen(sdpBuf)], 
  117. "a=mpeg4-iod: 42data:application/mpeg4-iod;base64,%s421512",
  118. iodBase64);
  119. SetSessionSdp(sdpBuf);
  120. VERBOSE_ISMA(GetVerbosity(),
  121. printf("IOD SDP = %sn", sdpBuf));
  122. MP4Free(iodBase64);
  123. iodBase64 = NULL;
  124. MP4Free(pBytes);
  125. pBytes = NULL;
  126. MP4Free(sdpBuf);
  127. sdpBuf = NULL;
  128. }
  129. static void CloneIntegerProperty(
  130. MP4Descriptor* pDest, 
  131. MP4DescriptorProperty* pSrc,
  132. const char* name)
  133. {
  134. MP4IntegerProperty* pGetProperty;
  135. MP4IntegerProperty* pSetProperty;
  136. pSrc->FindProperty(name, (MP4Property**)&pGetProperty);
  137. pDest->FindProperty(name, (MP4Property**)&pSetProperty);
  138. pSetProperty->SetValue(pGetProperty->GetValue());
  139. void MP4File::CreateIsmaIodFromFile(
  140. MP4TrackId odTrackId,
  141. MP4TrackId sceneTrackId,
  142. MP4TrackId audioTrackId, 
  143. MP4TrackId videoTrackId,
  144. u_int8_t** ppBytes,
  145. u_int64_t* pNumBytes)
  146. {
  147. MP4Descriptor* pIod = new MP4IODescriptor();
  148. pIod->SetTag(MP4IODescrTag);
  149. pIod->Generate();
  150. MP4Atom* pIodsAtom = FindAtom("moov.iods");
  151. ASSERT(pIodsAtom);
  152. MP4DescriptorProperty* pSrcIod = 
  153. (MP4DescriptorProperty*)pIodsAtom->GetProperty(2);
  154. CloneIntegerProperty(pIod, pSrcIod, "objectDescriptorId");
  155. CloneIntegerProperty(pIod, pSrcIod, "ODProfileLevelId");
  156. CloneIntegerProperty(pIod, pSrcIod, "sceneProfileLevelId");
  157. CloneIntegerProperty(pIod, pSrcIod, "audioProfileLevelId");
  158. CloneIntegerProperty(pIod, pSrcIod, "visualProfileLevelId");
  159. CloneIntegerProperty(pIod, pSrcIod, "graphicsProfileLevelId");
  160. // mutate esIds from MP4ESIDIncDescrTag to MP4ESDescrTag
  161. MP4DescriptorProperty* pEsProperty;
  162. pIod->FindProperty("esIds", (MP4Property**)&pEsProperty);
  163. pEsProperty->SetTags(MP4ESDescrTag);
  164. MP4IntegerProperty* pSetProperty;
  165. // OD
  166. MP4Descriptor* pOdEsd =
  167. pEsProperty->AddDescriptor(MP4ESDescrTag);
  168. pOdEsd->Generate();
  169. pOdEsd->FindProperty("ESID", 
  170. (MP4Property**)&pSetProperty);
  171. pSetProperty->SetValue(m_odTrackId);
  172. pOdEsd->FindProperty("URLFlag", 
  173. (MP4Property**)&pSetProperty);
  174. pSetProperty->SetValue(1);
  175. u_int8_t* pBytes;
  176. u_int64_t numBytes;
  177. CreateIsmaODUpdateCommandFromFileForStream(
  178. audioTrackId, 
  179. videoTrackId,
  180. &pBytes, 
  181. &numBytes);
  182. VERBOSE_ISMA(GetVerbosity(),
  183. printf("OD data =n"); MP4HexDump(pBytes, numBytes));
  184. char* odCmdBase64 = MP4ToBase64(pBytes, numBytes);
  185. char* urlBuf = (char*)MP4Malloc(strlen(odCmdBase64) + 64);
  186. sprintf(urlBuf, 
  187. "data:application/mpeg4-od-au;base64,%s",
  188. odCmdBase64);
  189. MP4StringProperty* pUrlProperty;
  190. pOdEsd->FindProperty("URL", 
  191. (MP4Property**)&pUrlProperty);
  192. pUrlProperty->SetValue(urlBuf);
  193. VERBOSE_ISMA(GetVerbosity(),
  194. printf("OD data URL = 42%s42n", urlBuf));
  195. MP4Free(odCmdBase64);
  196. odCmdBase64 = NULL;
  197. MP4Free(pBytes);
  198. pBytes = NULL;
  199. MP4Free(urlBuf);
  200. urlBuf = NULL;
  201. MP4DescriptorProperty* pSrcDcd = NULL;
  202. // HACK temporarily point to scene decoder config
  203. FindProperty(MakeTrackName(odTrackId, 
  204. "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr"),
  205. (MP4Property**)&pSrcDcd);
  206. ASSERT(pSrcDcd);
  207. MP4Property* pOrgOdEsdProperty = 
  208. pOdEsd->GetProperty(8);
  209. pOdEsd->SetProperty(8, pSrcDcd);
  210. // bufferSizeDB needs to be set appropriately
  211. MP4BitfieldProperty* pBufferSizeProperty = NULL;
  212. pOdEsd->FindProperty("decConfigDescr.bufferSizeDB",
  213. (MP4Property**)&pBufferSizeProperty);
  214. ASSERT(pBufferSizeProperty);
  215. pBufferSizeProperty->SetValue(numBytes);
  216. // SL config needs to change from 2 (file) to 1 (null)
  217. pOdEsd->FindProperty("slConfigDescr.predefined", 
  218. (MP4Property**)&pSetProperty);
  219. pSetProperty->SetValue(1);
  220. // Scene
  221. MP4Descriptor* pSceneEsd =
  222. pEsProperty->AddDescriptor(MP4ESDescrTag);
  223. pSceneEsd->Generate();
  224. pSceneEsd->FindProperty("ESID", 
  225. (MP4Property**)&pSetProperty);
  226. pSetProperty->SetValue(sceneTrackId);
  227. pSceneEsd->FindProperty("URLFlag", 
  228. (MP4Property**)&pSetProperty);
  229. pSetProperty->SetValue(1);
  230. CreateIsmaSceneCommand(
  231. MP4_IS_VALID_TRACK_ID(audioTrackId), 
  232. MP4_IS_VALID_TRACK_ID(videoTrackId),
  233. &pBytes, 
  234. &numBytes);
  235. VERBOSE_ISMA(GetVerbosity(),
  236. printf("Scene data =n"); MP4HexDump(pBytes, numBytes));
  237. char *sceneCmdBase64 = MP4ToBase64(pBytes, numBytes);
  238. urlBuf = (char*)MP4Malloc(strlen(sceneCmdBase64) + 64);
  239. sprintf(urlBuf, 
  240. "data:application/mpeg4-bifs-au;base64,%s",
  241. sceneCmdBase64);
  242. pSceneEsd->FindProperty("URL", 
  243. (MP4Property**)&pUrlProperty);
  244. pUrlProperty->SetValue(urlBuf);
  245. VERBOSE_ISMA(GetVerbosity(),
  246. printf("Scene data URL = 42%s42n", urlBuf));
  247. MP4Free(sceneCmdBase64);
  248. sceneCmdBase64 = NULL;
  249. MP4Free(urlBuf);
  250. urlBuf = NULL;
  251. MP4Free(pBytes);
  252. pBytes = NULL;
  253. // HACK temporarily point to scene decoder config
  254. FindProperty(MakeTrackName(sceneTrackId, 
  255. "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr"),
  256. (MP4Property**)&pSrcDcd);
  257. ASSERT(pSrcDcd);
  258. MP4Property* pOrgSceneEsdProperty = 
  259. pSceneEsd->GetProperty(8);
  260. pSceneEsd->SetProperty(8, pSrcDcd);
  261. // bufferSizeDB needs to be set
  262. pBufferSizeProperty = NULL;
  263. pSceneEsd->FindProperty("decConfigDescr.bufferSizeDB",
  264. (MP4Property**)&pBufferSizeProperty);
  265. ASSERT(pBufferSizeProperty);
  266. pBufferSizeProperty->SetValue(numBytes);
  267. // SL config needs to change from 2 (file) to 1 (null)
  268. pSceneEsd->FindProperty("slConfigDescr.predefined", 
  269. (MP4Property**)&pSetProperty);
  270. pSetProperty->SetValue(1);
  271. // finally get the whole thing written to a memory 
  272. pIod->WriteToMemory(this, ppBytes, pNumBytes);
  273. // now carefully replace esd properties before destroying
  274. pOdEsd->SetProperty(8, pOrgOdEsdProperty);
  275. pSceneEsd->SetProperty(8, pOrgSceneEsdProperty);
  276. delete pIod;
  277. VERBOSE_ISMA(GetVerbosity(),
  278. printf("IOD data =n"); MP4HexDump(*ppBytes, *pNumBytes));
  279. }
  280. void MP4File::CreateIsmaIodFromParams(
  281. u_int8_t videoProfile,
  282. u_int32_t videoBitrate,
  283. u_int8_t* videoConfig,
  284. u_int32_t videoConfigLength,
  285. u_int8_t audioProfile,
  286. u_int32_t audioBitrate,
  287. u_int8_t* audioConfig,
  288. u_int32_t audioConfigLength,
  289. u_int8_t** ppIodBytes,
  290. u_int64_t* pIodNumBytes)
  291. {
  292. MP4IntegerProperty* pInt;
  293. u_int8_t* pBytes = NULL;
  294. u_int64_t numBytes;
  295. // Create the IOD
  296. MP4Descriptor* pIod = new MP4IODescriptor();
  297. pIod->SetTag(MP4IODescrTag);
  298. pIod->Generate();
  299. // Set audio and video profileLevels
  300. pIod->FindProperty("audioProfileLevelId", 
  301. (MP4Property**)&pInt);
  302. pInt->SetValue(audioProfile);
  303. pIod->FindProperty("visualProfileLevelId", 
  304. (MP4Property**)&pInt);
  305. pInt->SetValue(videoProfile);
  306. // Mutate esIds from MP4ESIDIncDescrTag to MP4ESDescrTag
  307. MP4DescriptorProperty* pEsProperty;
  308. pIod->FindProperty("esIds", (MP4Property**)&pEsProperty);
  309. pEsProperty->SetTags(MP4ESDescrTag);
  310. // Add ES Descriptors
  311. // Scene
  312. CreateIsmaSceneCommand(
  313. (audioProfile != 0xFF),
  314. (videoProfile != 0xFF),
  315. &pBytes, 
  316. &numBytes);
  317. VERBOSE_ISMA(GetVerbosity(),
  318. printf("Scene data =n"); MP4HexDump(pBytes, numBytes));
  319. char* sceneCmdBase64 = MP4ToBase64(pBytes, numBytes);
  320. char* urlBuf = 
  321. (char*)MP4Malloc(strlen(sceneCmdBase64) + 64);
  322. sprintf(urlBuf, 
  323. "data:application/mpeg4-bifs-au;base64,%s",
  324. sceneCmdBase64);
  325. VERBOSE_ISMA(GetVerbosity(),
  326. printf("Scene data URL = 42%s42n", urlBuf));
  327. MP4Descriptor* pSceneEsd =
  328. CreateESD(
  329. pEsProperty,
  330. 201, // esid
  331. MP4SystemsV2ObjectType,
  332. MP4SceneDescriptionStreamType,
  333. numBytes, // bufferSize
  334. numBytes * 8, // bitrate
  335. BifsV2Config,
  336. sizeof(BifsV2Config),
  337. urlBuf);
  338. MP4Free(sceneCmdBase64);
  339. sceneCmdBase64 = NULL;
  340. MP4Free(urlBuf);
  341. urlBuf = NULL;
  342. MP4Free(pBytes);
  343. pBytes = NULL;
  344. // Video
  345. MP4Descriptor* pVideoEsd =
  346. CreateESD(
  347. pEsProperty,
  348. 20, // esid
  349. MP4_MPEG4_VIDEO_TYPE,
  350. MP4VisualStreamType,
  351. videoBitrate / 8, // bufferSize
  352. videoBitrate,
  353. videoConfig,
  354. videoConfigLength,
  355. NULL);
  356. // Audio
  357. MP4Descriptor* pAudioEsd =
  358. CreateESD(
  359. pEsProperty,
  360. 10, // esid
  361. MP4_MPEG4_AUDIO_TYPE,
  362. MP4AudioStreamType,
  363. audioBitrate / 8,  // bufferSize
  364. audioBitrate,
  365. audioConfig,
  366. audioConfigLength,
  367. NULL);
  368. // OD
  369. // Glop to make infrastructure happy
  370. MP4DescriptorProperty* pAudioEsdProperty =
  371. new MP4DescriptorProperty();
  372. pAudioEsdProperty->AppendDescriptor(pAudioEsd);
  373. MP4DescriptorProperty* pVideoEsdProperty =
  374. new MP4DescriptorProperty();
  375. pVideoEsdProperty->AppendDescriptor(pVideoEsd);
  376. CreateIsmaODUpdateCommandForStream(
  377. pAudioEsdProperty,
  378. pVideoEsdProperty, 
  379. &pBytes,
  380. &numBytes);
  381. // TBD cleanup temporary descriptor properties
  382. VERBOSE_ISMA(GetVerbosity(),
  383. printf("OD data =n"); MP4HexDump(pBytes, numBytes));
  384. char* odCmdBase64 = MP4ToBase64(pBytes, numBytes);
  385. urlBuf = (char*)MP4Malloc(strlen(odCmdBase64) + 64);
  386. sprintf(urlBuf, 
  387. "data:application/mpeg4-od-au;base64,%s",
  388. odCmdBase64);
  389. VERBOSE_ISMA(GetVerbosity(),
  390. printf("OD data URL = 42%s42n", urlBuf));
  391. MP4Descriptor* pOdEsd =
  392. CreateESD(
  393. pEsProperty,
  394. 101,
  395. MP4SystemsV1ObjectType,
  396. MP4ObjectDescriptionStreamType,
  397. numBytes, // bufferSize
  398. numBytes * 8, // bitrate
  399. NULL, // config
  400. 0, // configLength
  401. urlBuf);
  402. MP4Free(odCmdBase64);
  403. odCmdBase64 = NULL;
  404. MP4Free(pBytes);
  405. pBytes = NULL;
  406. MP4Free(urlBuf);
  407. urlBuf = NULL;
  408. // finally get the whole thing written to a memory 
  409. pIod->WriteToMemory(this, ppIodBytes, pIodNumBytes);
  410. delete pIod;
  411. VERBOSE_ISMA(GetVerbosity(),
  412. printf("IOD data =n"); MP4HexDump(*ppIodBytes, *pIodNumBytes));
  413. }
  414. MP4Descriptor* MP4File::CreateESD(
  415. MP4DescriptorProperty* pEsProperty,
  416. u_int32_t esid,
  417. u_int8_t objectType,
  418. u_int8_t streamType,
  419. u_int32_t bufferSize,
  420. u_int32_t bitrate,
  421. u_int8_t* pConfig,
  422. u_int32_t configLength,
  423. char* url)
  424. {
  425. MP4IntegerProperty* pInt;
  426. MP4StringProperty* pString;
  427. MP4BytesProperty* pBytes;
  428. MP4Descriptor* pEsd =
  429. pEsProperty->AddDescriptor(MP4ESDescrTag);
  430. pEsd->Generate();
  431. pEsd->FindProperty("ESID", 
  432. (MP4Property**)&pInt);
  433. pInt->SetValue(esid);
  434. pEsd->FindProperty("decConfigDescr.objectTypeId", 
  435. (MP4Property**)&pInt);
  436. pInt->SetValue(objectType);
  437. pEsd->FindProperty("decConfigDescr.streamType", 
  438. (MP4Property**)&pInt);
  439. pInt->SetValue(streamType);
  440. pEsd->FindProperty("decConfigDescr.bufferSizeDB", 
  441. (MP4Property**)&pInt);
  442. pInt->SetValue(bufferSize);
  443. pEsd->FindProperty("decConfigDescr.maxBitrate", 
  444. (MP4Property**)&pInt);
  445. pInt->SetValue(bitrate);
  446. pEsd->FindProperty("decConfigDescr.avgBitrate", 
  447. (MP4Property**)&pInt);
  448. pInt->SetValue(bitrate);
  449. MP4DescriptorProperty* pConfigDescrProperty;
  450. pEsd->FindProperty("decConfigDescr.decSpecificInfo",
  451. (MP4Property**)&pConfigDescrProperty);
  452. MP4Descriptor* pConfigDescr =
  453. pConfigDescrProperty->AddDescriptor(MP4DecSpecificDescrTag);
  454. pConfigDescr->Generate();
  455. pConfigDescrProperty->FindProperty("decSpecificInfo[0].info",
  456. (MP4Property**)&pBytes);
  457. pBytes->SetValue(pConfig, configLength);
  458. pEsd->FindProperty("slConfigDescr.predefined", 
  459. (MP4Property**)&pInt);
  460. pInt->SetValue(1);
  461. if (url) {
  462. pEsd->FindProperty("URLFlag", 
  463. (MP4Property**)&pInt);
  464. pInt->SetValue(1);
  465. pEsd->FindProperty("URL", 
  466. (MP4Property**)&pString);
  467. pString->SetValue(url);
  468. }
  469. return pEsd;
  470. }
  471. void MP4File::CreateIsmaODUpdateCommandFromFileForFile(
  472. MP4TrackId odTrackId,
  473. MP4TrackId audioTrackId, 
  474. MP4TrackId videoTrackId,
  475. u_int8_t** ppBytes,
  476. u_int64_t* pNumBytes)
  477. {
  478. MP4Descriptor* pCommand = CreateODCommand(MP4ODUpdateODCommandTag);
  479. pCommand->Generate();
  480. for (u_int8_t i = 0; i < 2; i++) {
  481. MP4TrackId trackId;
  482. u_int16_t odId;
  483. if (i == 0) {
  484. trackId = audioTrackId;
  485. odId = 10;
  486. } else {
  487. trackId = videoTrackId;
  488. odId = 20;
  489. }
  490. if (trackId == MP4_INVALID_TRACK_ID) {
  491. continue;
  492. }
  493. MP4DescriptorProperty* pOdDescrProperty =
  494. (MP4DescriptorProperty*)(pCommand->GetProperty(0));
  495. pOdDescrProperty->SetTags(MP4FileODescrTag);
  496. MP4Descriptor* pOd =
  497. pOdDescrProperty->AddDescriptor(MP4FileODescrTag);
  498. pOd->Generate();
  499. MP4BitfieldProperty* pOdIdProperty = NULL;
  500. pOd->FindProperty("objectDescriptorId", 
  501. (MP4Property**)&pOdIdProperty);
  502. pOdIdProperty->SetValue(odId);
  503. MP4DescriptorProperty* pEsIdsDescriptorProperty = NULL;
  504. pOd->FindProperty("esIds", 
  505. (MP4Property**)&pEsIdsDescriptorProperty);
  506. ASSERT(pEsIdsDescriptorProperty);
  507. pEsIdsDescriptorProperty->SetTags(MP4ESIDRefDescrTag);
  508. MP4Descriptor *pRefDescriptor =
  509. pEsIdsDescriptorProperty->AddDescriptor(MP4ESIDRefDescrTag);
  510. pRefDescriptor->Generate();
  511. MP4Integer16Property* pRefIndexProperty = NULL;
  512. pRefDescriptor->FindProperty("refIndex", 
  513. (MP4Property**)&pRefIndexProperty);
  514. ASSERT(pRefIndexProperty);
  515. u_int32_t mpodIndex = FindTrackReference(
  516. MakeTrackName(odTrackId, "tref.mpod"), trackId);
  517. ASSERT(mpodIndex != 0);
  518. pRefIndexProperty->SetValue(mpodIndex);
  519. }
  520. pCommand->WriteToMemory(this, ppBytes, pNumBytes);
  521. delete pCommand;
  522. }
  523. void MP4File::CreateIsmaODUpdateCommandFromFileForStream(
  524. MP4TrackId audioTrackId, 
  525. MP4TrackId videoTrackId,
  526. u_int8_t** ppBytes,
  527. u_int64_t* pNumBytes)
  528. {
  529. MP4DescriptorProperty* pAudioEsd = NULL;
  530. MP4Integer8Property* pAudioSLConfig = NULL;
  531. MP4DescriptorProperty* pVideoEsd = NULL;
  532. MP4Integer8Property* pVideoSLConfig = NULL;
  533. if (audioTrackId != MP4_INVALID_TRACK_ID) {
  534. MP4Atom* pEsdsAtom = 
  535. FindAtom(MakeTrackName(audioTrackId, 
  536. "mdia.minf.stbl.stsd.mp4a.esds"));
  537. ASSERT(pEsdsAtom);
  538. pAudioEsd = (MP4DescriptorProperty*)(pEsdsAtom->GetProperty(2));
  539. // SL config needs to change from 2 (file) to 1 (null)
  540. pAudioEsd->FindProperty("slConfigDescr.predefined", 
  541. (MP4Property**)&pAudioSLConfig);
  542. ASSERT(pAudioSLConfig);
  543. pAudioSLConfig->SetValue(1);
  544. }
  545. if (videoTrackId != MP4_INVALID_TRACK_ID) {
  546. MP4Atom* pEsdsAtom = 
  547. FindAtom(MakeTrackName(videoTrackId, 
  548. "mdia.minf.stbl.stsd.mp4v.esds"));
  549. ASSERT(pEsdsAtom);
  550. pVideoEsd = (MP4DescriptorProperty*)(pEsdsAtom->GetProperty(2));
  551. // SL config needs to change from 2 (file) to 1 (null)
  552. pVideoEsd->FindProperty("slConfigDescr.predefined", 
  553. (MP4Property**)&pVideoSLConfig);
  554. ASSERT(pVideoSLConfig);
  555. pVideoSLConfig->SetValue(1);
  556. }
  557. CreateIsmaODUpdateCommandForStream(
  558. pAudioEsd, pVideoEsd, ppBytes, pNumBytes);
  559. // return SL config values to 2 (file)
  560. if (pAudioSLConfig) {
  561. pAudioSLConfig->SetValue(2);
  562. }
  563. if (pVideoSLConfig) {
  564. pVideoSLConfig->SetValue(2);
  565. }
  566. }
  567. void MP4File::CreateIsmaODUpdateCommandForStream(
  568. MP4DescriptorProperty* pAudioEsdProperty, 
  569. MP4DescriptorProperty* pVideoEsdProperty,
  570. u_int8_t** ppBytes,
  571. u_int64_t* pNumBytes)
  572. {
  573. MP4Descriptor* pAudioOd = NULL;
  574. MP4Descriptor* pVideoOd = NULL;
  575. MP4Descriptor* pCommand = 
  576. CreateODCommand(MP4ODUpdateODCommandTag);
  577. pCommand->Generate();
  578. for (u_int8_t i = 0; i < 2; i++) {
  579. u_int16_t odId;
  580. MP4DescriptorProperty* pEsdProperty = NULL;
  581. if (i == 0) {
  582. odId = 10;
  583. pEsdProperty = pAudioEsdProperty;
  584. } else {
  585. odId = 20;
  586. pEsdProperty = pVideoEsdProperty;
  587. }
  588. if (pEsdProperty == NULL) {
  589. continue;
  590. }
  591. MP4DescriptorProperty* pOdDescrProperty =
  592. (MP4DescriptorProperty*)(pCommand->GetProperty(0));
  593. pOdDescrProperty->SetTags(MP4ODescrTag);
  594. MP4Descriptor* pOd =
  595. pOdDescrProperty->AddDescriptor(MP4ODescrTag);
  596. pOd->Generate();
  597. if (i == 0) {
  598. pAudioOd = pOd;
  599. } else {
  600. pVideoOd = pOd;
  601. }
  602. MP4BitfieldProperty* pOdIdProperty = NULL;
  603. pOd->FindProperty("objectDescriptorId", 
  604. (MP4Property**)&pOdIdProperty);
  605. pOdIdProperty->SetValue(odId);
  606. delete (MP4DescriptorProperty*)pOd->GetProperty(4);
  607. pOd->SetProperty(4, pEsdProperty);
  608. }
  609. // serialize OD command
  610. pCommand->WriteToMemory(this, ppBytes, pNumBytes);
  611. // detach from esd descriptor params
  612. if (pAudioOd) {
  613. pAudioOd->SetProperty(4, NULL);
  614. }
  615. if (pVideoOd) {
  616. pVideoOd->SetProperty(4, NULL);
  617. }
  618. // then destroy
  619. delete pCommand;
  620. }
  621. void MP4File::CreateIsmaSceneCommand(
  622. bool hasAudio,
  623. bool hasVideo,
  624. u_int8_t** ppBytes,
  625. u_int64_t* pNumBytes)
  626. {
  627. // from ISMA 1.0 Tech Spec Appendix E
  628. static u_int8_t bifsAudioOnly[] = {
  629. 0xC0, 0x10, 0x12, 
  630. 0x81, 0x30, 0x2A, 0x05, 0x7C
  631. };
  632. static u_int8_t bifsVideoOnly[] = {
  633. 0xC0, 0x10, 0x12, 
  634. 0x61, 0x04, 0x88, 0x50, 0x45, 0x05, 0x3F, 0x00
  635. };
  636. static u_int8_t bifsAudioVideo[] = {
  637. 0xC0, 0x10, 0x12, 
  638. 0x81, 0x30, 0x2A, 0x05, 0x72,
  639. 0x61, 0x04, 0x88, 0x50, 0x45, 0x05, 0x3F, 0x00
  640. };
  641. if (hasAudio && hasVideo) {
  642. *pNumBytes = sizeof(bifsAudioVideo);
  643. *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes);
  644. memcpy(*ppBytes, bifsAudioVideo, sizeof(bifsAudioVideo));
  645. } else if (hasAudio) {
  646. *pNumBytes = sizeof(bifsAudioOnly);
  647. *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes);
  648. memcpy(*ppBytes, bifsAudioOnly, sizeof(bifsAudioOnly));
  649. } else if (hasVideo) {
  650. *pNumBytes = sizeof(bifsVideoOnly);
  651. *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes);
  652. memcpy(*ppBytes, bifsVideoOnly, sizeof(bifsVideoOnly));
  653. } else {
  654. *pNumBytes = 0;
  655. *ppBytes = NULL;
  656. }
  657. }