1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 /*********************************************************************************/ 19 /* ------------------------------------------------------------------- */ 20 /* MPEG-4 Track Fragment Atom Class */ 21 /* ------------------------------------------------------------------- */ 22 /*********************************************************************************/ 23 /* 24 */ 25 26 #define IMPLEMENT_MovieFragmentRandomAccessAtom 27 28 #include "atomdefs.h" 29 #include "atomutils.h" 30 #include "moviefragmentrandomaccess.h" 31 32 typedef Oscl_Vector<TrackFragmentRandomAccessAtom*, OsclMemAllocator> trackFragmentRandomAccessAtomVecType; 33 34 // Constructor 35 MovieFragmentRandomAccessAtom::MovieFragmentRandomAccessAtom(MP4_FF_FILE *fp, 36 uint32 size, 37 uint32 type) 38 : Atom(fp, size, type) 39 { 40 _pTrackFragmentRandomAccessAtomVec = NULL; 41 _pMfraOffsetAtom = NULL; 42 #if (DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT) 43 // This will store the entry count of TFRA for Video for Vonly,AVT,AV,VT clips and Audio TFRA entry count for Aonly,AT clips 44 // and Text TFRA entry count for Tonly clips. 45 oVideoAudioTextTrackTfraCount = 0; 46 #endif // DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT 47 48 iLogger = PVLogger::GetLoggerObject("mp4ffparser"); 49 iStateVarLogger = PVLogger::GetLoggerObject("mp4ffparser_mediasamplestats"); 50 iParsedDataLogger = PVLogger::GetLoggerObject("mp4ffparser_parseddata"); 51 52 uint32 count = size - DEFAULT_ATOM_SIZE; 53 if (_success) 54 { 55 PV_MP4_FF_NEW(fp->auditCB, trackFragmentRandomAccessAtomVecType, (), _pTrackFragmentRandomAccessAtomVec); 56 while (count > 0) 57 { 58 uint32 atomType = UNKNOWN_ATOM; 59 uint32 atomSize = 0; 60 AtomUtils::getNextAtomType(fp, atomSize, atomType); 61 62 if (atomType == MOVIE_FRAGMENT_RANDOM_ACCESS_OFFSET_ATOM) 63 { 64 if (_pMfraOffsetAtom == NULL) 65 { 66 PV_MP4_FF_NEW(fp->auditCB, MfraOffsetAtom, (fp, atomSize, atomType), _pMfraOffsetAtom); 67 if (!_pMfraOffsetAtom->MP4Success()) 68 { 69 _success = false; 70 _mp4ErrorCode = READ_MOVIE_FRAGMENT_RANDOM_ACCESS_OFFSET_FAILED; 71 return; 72 } 73 count -= _pMfraOffsetAtom->getSize(); 74 } 75 else 76 { 77 //duplicate atom 78 count -= atomSize; 79 atomSize -= DEFAULT_ATOM_SIZE; 80 AtomUtils::seekFromCurrPos(fp, atomSize); 81 } 82 } 83 else if (atomType == TRACK_FRAGMENT_RANDOM_ACCESS_ATOM) 84 { 85 TrackFragmentRandomAccessAtom *pTrackFragmentRandomAccessAtom = NULL; 86 PV_MP4_FF_NEW(fp->auditCB, TrackFragmentRandomAccessAtom, (fp, atomSize, atomType), 87 pTrackFragmentRandomAccessAtom); 88 if (!pTrackFragmentRandomAccessAtom->MP4Success()) 89 { 90 PV_MP4_FF_DELETE(NULL, TrackFragmentRandomAccessAtom, pTrackFragmentRandomAccessAtom); 91 _success = false; 92 _mp4ErrorCode = READ_TRACK_FRAGMENT_RANDOM_ACCESS_ATOM_FAILED; 93 return; 94 } 95 count -= pTrackFragmentRandomAccessAtom->getSize(); 96 _pTrackFragmentRandomAccessAtomVec->push_back(pTrackFragmentRandomAccessAtom); 97 } 98 99 } 100 } 101 else 102 { 103 _mp4ErrorCode = READ_MOVIE_FRAGMENT_RANDOM_ACCESS_ATOM_FAILED; 104 } 105 } 106 107 MovieFragmentRandomAccessAtom::~MovieFragmentRandomAccessAtom() 108 { 109 if (_pMfraOffsetAtom != NULL) 110 { 111 PV_MP4_FF_DELETE(NULL, MfraOffsetAtom, _pMfraOffsetAtom); 112 } 113 114 for (uint32 i = 0; i < _pTrackFragmentRandomAccessAtomVec->size(); i++) 115 { 116 PV_MP4_FF_DELETE(NULL, TrackFragmentRandomAccessAtom, (*_pTrackFragmentRandomAccessAtomVec)[i]); 117 } 118 PV_MP4_FF_TEMPLATED_DELETE(NULL, trackFragmentRandomAccessAtomVecType, Oscl_Vector, _pTrackFragmentRandomAccessAtomVec); 119 120 } 121 122 bool MovieFragmentRandomAccessAtom::IsTFRAPresentForTrack(uint32 trackID, bool oVideoAudioTextTrack) 123 { 124 125 uint32 num_tfra = 0; 126 if (_pTrackFragmentRandomAccessAtomVec != NULL) 127 { 128 num_tfra = _pTrackFragmentRandomAccessAtomVec->size(); 129 for (uint32 idx = 0; idx < num_tfra; idx++) 130 { 131 TrackFragmentRandomAccessAtom *tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx]; 132 if (tfraAtom->getTrackID() == trackID) 133 { 134 if (tfraAtom->_entry_count > 0) 135 { 136 #if (DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT) 137 if (oVideoAudioTextTrack) 138 { 139 oVideoAudioTextTrackTfraCount = tfraAtom->_entry_count; 140 // If oVideoAudioTextTrack flag is set we just store the entry count to be checked 141 // for other tracks. 142 return true; 143 } 144 else if (oVideoAudioTextTrackTfraCount == tfraAtom->_entry_count) 145 #else 146 OSCL_UNUSED_ARG(oVideoAudioTextTrack); 147 #endif // DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT 148 { 149 return true; 150 } 151 } 152 } 153 } 154 } 155 return false; 156 157 } 158 int32 MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime(uint32 trackID, uint32 &time, uint32 &moof_offset, 159 uint32 &traf_number, uint32 &trun_number, 160 uint32 &sample_num) 161 { 162 uint32 num_tfra = 0; 163 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Input Time =%d", time)); 164 if (_pTrackFragmentRandomAccessAtomVec == NULL) 165 { 166 return -1; 167 }; 168 num_tfra = _pTrackFragmentRandomAccessAtomVec->size(); 169 for (uint32 idx = 0; idx < num_tfra; idx++) 170 { 171 TrackFragmentRandomAccessAtom *tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx]; 172 if (! tfraAtom) // (unlikely) 173 return -1; 174 if (tfraAtom->getTrackID() == trackID) 175 { 176 uint32 entries = tfraAtom->_entry_count; 177 if (entries == 0) 178 return -1; 179 180 Oscl_Vector<TFRAEntries*, OsclMemAllocator>* tfraEntries = tfraAtom->getTrackFragmentRandomAccessEntries(); 181 if (!tfraEntries) // unlikely/error 182 return -1; 183 int32 prevTime = 0; 184 for (uint32 idy = 0; idy < entries; idy++) 185 { 186 if (time < (*tfraEntries)[idy]->getTimeStamp()) 187 { 188 uint32 tmp = (*tfraEntries)[idy]->getTimeStamp(); 189 uint32 diffwithbeforeTS = time - prevTime; 190 uint32 diffwithafterTS = tmp - time; 191 if (diffwithbeforeTS > diffwithafterTS) 192 { 193 time = tmp; 194 moof_offset = (*tfraEntries)[idy]->getTimeMoofOffset(); 195 traf_number = (*tfraEntries)[idy]->_traf_number; 196 trun_number = (*tfraEntries)[idy]->_trun_number; 197 sample_num = (*tfraEntries)[idy]->_sample_number; 198 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time)); 199 return 0; 200 } 201 else 202 { 203 time = prevTime; 204 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time)); 205 return 0; 206 } 207 } 208 moof_offset = (*tfraEntries)[idy]->getTimeMoofOffset(); 209 traf_number = (*tfraEntries)[idy]->_traf_number; 210 trun_number = (*tfraEntries)[idy]->_trun_number; 211 sample_num = (*tfraEntries)[idy]->_sample_number; 212 213 prevTime = (*tfraEntries)[idy]->getTimeStamp(); 214 } 215 time = prevTime; 216 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time)); 217 return 0; 218 } 219 } 220 221 // error return if we get here. 222 return -1; 223 } 224 225 int32 MovieFragmentRandomAccessAtom::queryRepositionTime(uint32 trackID, int32 time, bool oDependsOn, bool bBeforeRequestedTime) 226 { 227 OSCL_UNUSED_ARG(oDependsOn); 228 229 uint32 num_tfra = 0; 230 int32 closestTime = 0; 231 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Input Time =%d", time)); 232 if (_pTrackFragmentRandomAccessAtomVec != NULL) 233 { 234 num_tfra = _pTrackFragmentRandomAccessAtomVec->size(); 235 for (uint32 idx = 0; idx < num_tfra; idx++) 236 { 237 TrackFragmentRandomAccessAtom* tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx]; 238 if (tfraAtom->getTrackID() == trackID) 239 { 240 uint32 entries = tfraAtom->_entry_count; 241 Oscl_Vector<TFRAEntries*, OsclMemAllocator>* tfraEntries = tfraAtom->getTrackFragmentRandomAccessEntries(); 242 if (!tfraEntries) // unlikely/error 243 return closestTime; 244 int32 prevTime = 0; 245 for (uint32 idy = 0; idy < entries; idy++) 246 { 247 if (bBeforeRequestedTime) 248 { 249 if (time < (int32)(*tfraEntries)[idy]->getTimeStamp()) 250 { 251 time = prevTime; 252 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time)); 253 break; 254 } 255 else if ((time == (int32)(*tfraEntries)[idy]->getTimeStamp()) || 256 ((idy == (entries - 1)) && (time > (int32)(*tfraEntries)[idy]->getTimeStamp()))) 257 { 258 time = (*tfraEntries)[idy]->getTimeStamp(); 259 break; 260 261 } 262 prevTime = (*tfraEntries)[idy]->getTimeStamp(); 263 } 264 else 265 { 266 if (time <= (int32)(*tfraEntries)[idy]->getTimeStamp()) 267 { 268 time = (*tfraEntries)[idy]->getTimeStamp(); 269 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time)); 270 break; 271 } 272 else if ((idy == (entries - 1)) && (time > (int32)(*tfraEntries)[idy]->getTimeStamp())) 273 { 274 time = (*tfraEntries)[idy]->getTimeStamp(); 275 break; 276 277 } 278 279 prevTime = (*tfraEntries)[idy]->getTimeStamp(); 280 281 } 282 } 283 closestTime = time; 284 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time)); 285 return closestTime; 286 } 287 } 288 } 289 return closestTime; 290 } 291 292 int32 MovieFragmentRandomAccessAtom::getTimestampForRandomAccessPoints(uint32 id, uint32 *num, uint32 *tsBuf, uint32* numBuf, uint32* offsetBuff, uint32 samplesFromMovie) 293 { 294 uint32 num_tfra = 0; 295 uint32 samplesfromMoov = samplesFromMovie; 296 TrackFragmentRandomAccessAtom *tfraAtom = NULL; 297 298 if (_pTrackFragmentRandomAccessAtomVec != NULL) 299 { 300 num_tfra = _pTrackFragmentRandomAccessAtomVec->size(); 301 302 for (uint32 idx = 0; idx < num_tfra; idx++) 303 { 304 tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx]; 305 if (tfraAtom->getTrackID() == id) 306 { 307 break; 308 } 309 } 310 } 311 if (tfraAtom != NULL) 312 { 313 uint32 entries = tfraAtom->_entry_count; 314 Oscl_Vector<TFRAEntries*, OsclMemAllocator>* tfraEntries = tfraAtom->getTrackFragmentRandomAccessEntries(); 315 if (!tfraEntries) // unlikely/error 316 return 0; 317 318 319 uint32 tmp = entries; 320 321 if (*num == 0) 322 { 323 *num = tmp; 324 return 1; //success. This is only the query mode. 325 } 326 327 uint32 sampleToBeRead = *num; 328 if (tmp < sampleToBeRead) 329 sampleToBeRead = tmp; 330 331 for (uint32 idx = samplesfromMoov; idx < sampleToBeRead + samplesfromMoov; idx++) 332 { 333 //it may crash if this buffer is not big enough 334 if (tsBuf != NULL) 335 tsBuf[idx] = (*tfraEntries)[idx]->getTimeStamp(); 336 if (numBuf) 337 numBuf[idx] = (*tfraEntries)[idx]->_sample_number; 338 if (offsetBuff) 339 offsetBuff[idx] = (*tfraEntries)[idx]->getTimeMoofOffset(); 340 } 341 *num = sampleToBeRead + samplesfromMoov; 342 343 return 1; //success 344 } 345 return 0; 346 } 347 348 349 int32 MovieFragmentRandomAccessAtom::getTimestampForRandomAccessPointsBeforeAfter(uint32 id, uint32 ts, uint32 *tsBuf, uint32* numBuf, 350 uint32& numsamplestoget, 351 uint32 howManyKeySamples) 352 { 353 uint32 num_tfra = 0, prevSampleNum = 0, sample_num = 0; 354 uint32 time = ts; 355 uint32 startIdx = 0, endIdx = 0; 356 357 TrackFragmentRandomAccessAtom *tfraAtom = NULL; 358 if (_pTrackFragmentRandomAccessAtomVec != NULL) 359 { 360 num_tfra = _pTrackFragmentRandomAccessAtomVec->size(); 361 362 for (uint32 idx = 0; idx < num_tfra; idx++) 363 { 364 tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx]; 365 if (tfraAtom != NULL) 366 { 367 if (tfraAtom->getTrackID() == id) 368 { 369 break; 370 } 371 } 372 } 373 } 374 if (tfraAtom != NULL) 375 { 376 uint32 entries = tfraAtom->_entry_count; 377 startIdx = entries; 378 endIdx = entries; 379 Oscl_Vector<TFRAEntries*, OsclMemAllocator>* tfraEntries = tfraAtom->getTrackFragmentRandomAccessEntries(); 380 if (!tfraEntries) // unlikely/error 381 return 0; 382 int32 prevTime = 0; 383 for (uint32 idy = 0; idy < entries; idy++) 384 { 385 if (time <= (*tfraEntries)[idy]->getTimeStamp()) 386 { 387 uint32 tmp = (*tfraEntries)[idy]->getTimeStamp(); 388 uint32 diffwithbeforeTS = time - prevTime; 389 uint32 diffwithafterTS = tmp - time; 390 if (diffwithbeforeTS > diffwithafterTS) 391 { 392 sample_num = (*tfraEntries)[idy]->_sample_number; 393 } 394 else 395 { 396 sample_num = prevSampleNum; 397 } 398 startIdx = idy; 399 endIdx = entries; 400 break; 401 } 402 prevSampleNum = (*tfraEntries)[idy]->_sample_number; 403 prevTime = (*tfraEntries)[idy]->getTimeStamp(); 404 } 405 if ((startIdx + howManyKeySamples) <= entries) 406 endIdx = startIdx + howManyKeySamples; 407 408 if (startIdx > howManyKeySamples) 409 startIdx -= howManyKeySamples; 410 else 411 { 412 startIdx = 0; 413 } 414 415 uint32 idx = 0; 416 uint32 k = 0; 417 for (idx = startIdx; idx < endIdx; idx++) 418 { 419 int32 keySampleNum = (*tfraEntries)[idx]->_sample_number; 420 int32 keySampleTS = (*tfraEntries)[idx]->getTimeStamp(); 421 numBuf[k] = keySampleNum; 422 tsBuf[k] = keySampleTS; 423 k++; 424 } 425 numsamplestoget = k; 426 } 427 else 428 return 0; 429 430 return 1; //success 431 432 } 433