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 SyncSampleAtom Class */ 21/* ------------------------------------------------------------------- */ 22/*********************************************************************************/ 23/* 24 This SyncSampleAtom Class provides a compact marking of the random access 25 points within the stream. 26*/ 27 28 29#define IMPLEMENT_SyncSampleAtom 30 31#include "syncsampleatom.h" 32#include "atomutils.h" 33#include "atomdefs.h" 34 35// Stream-in constructor 36SyncSampleAtom::SyncSampleAtom(MP4_FF_FILE *fp, uint32 size, uint32 type) 37 : FullAtom(fp, size, type) 38{ 39 _psampleNumbers = NULL; 40 41 if (_success) 42 { 43 44 _nextSampleNumber = 0; 45 46 if (!AtomUtils::read32(fp, _entryCount)) 47 { 48 _success = false; 49 } 50 51 uint32 dataSize = _size - (DEFAULT_FULL_ATOM_SIZE + 4); 52 53 uint32 entrySize = (4); 54 55 if ((_entryCount*entrySize) > dataSize) 56 { 57 _success = false; 58 } 59 60 if (_success) 61 { 62 63 PV_MP4_FF_ARRAY_NEW(NULL, uint32, (_entryCount), _psampleNumbers); 64 65 uint32 sync; 66 for (uint32 i = 0; i < _entryCount; i++) 67 { 68 if (!AtomUtils::read32(fp, sync)) 69 { 70 _success = false; 71 break; 72 } 73 _psampleNumbers[i] = (sync); 74 } 75 } 76 77 if (!_success) 78 _mp4ErrorCode = READ_SYNC_SAMPLE_ATOM_FAILED; 79 } 80 else 81 { 82 if (_mp4ErrorCode != ATOM_VERSION_NOT_SUPPORTED) 83 _mp4ErrorCode = READ_SYNC_SAMPLE_ATOM_FAILED; 84 } 85} 86 87// Destructor 88SyncSampleAtom::~SyncSampleAtom() 89{ 90 // Cleanup vector 91 if (_psampleNumbers != NULL) 92 { 93 PV_MP4_ARRAY_DELETE(NULL, _psampleNumbers); 94 _psampleNumbers = NULL; 95 } 96} 97 98// Returns the sync sample number at vector location 'index' 99int32 100SyncSampleAtom::getSampleNumberAt(int32 index) const 101{ 102 if (index < (int32)_entryCount) 103 { 104 return (_psampleNumbers[index] - 1); 105 } 106 else 107 { 108 return PV_ERROR; 109 } 110} 111 112// Returns the first sync sample that occurs at or after 'sampleNum'. This is used 113// when seeking in the bitstream trying to find a random access sample. This method 114// returns the random access sample that is closest immediately following 'sampleNum' 115int32 116SyncSampleAtom::getSyncSampleFollowing(uint32 sampleNum) const 117{ 118 uint32 sync = 0; 119 int32 count = 0; 120 while (sync < sampleNum) 121 { 122 if (count < (int32)_entryCount) 123 { 124 sync = _psampleNumbers[count] - 1; 125 count ++; 126 } 127 else 128 { 129 return PV_ERROR; 130 } 131 } 132 133 // Incase the sampleNum is one of the sync sample the existing sync 134 // is same as sampleNum In this way the sample return from getSyncSampleFollowing 135 // and getSyncSampleBefore become same causing repos issue. This check 136 // will advance the sync to next I frame incase it is available 137 if (sync == sampleNum) 138 { 139 if (count < (int32)_entryCount) 140 { 141 sync = _psampleNumbers[count] - 1; 142 } 143 144 // No I frame ahead exists, return 0 will ensure that engine ignore reposition and continue playing from current position 145 else 146 { 147 sync = 0; 148 } 149 } 150 151 return sync; 152} 153 154// Returns the first sync sample that occurs at or after 'sampleNum'. This is used 155// when seeking in the bitstream trying to find a random access sample. This method 156// returns the random access sample that is closest immediately following 'sampleNum' 157int32 158SyncSampleAtom::getSyncSampleBefore(uint32 sampleNum) const 159{ 160 uint32 sync = 0; 161 int32 count = 0; 162 163 //fix resetPlayback at the end of bitstream 164 //_asm {int 3}; 165 166 while ((sync < sampleNum) && 167 (count < (int32)_entryCount)) 168 { 169 sync = _psampleNumbers[count] - 1; 170 count ++; 171 } 172 173 //the nearest I frame before sampleNum 174 if (sync <= sampleNum) 175 return sync; 176 else 177 { 178 count = count - 2; 179 sync = _psampleNumbers[count] - 1; 180 return sync; 181 } 182} 183 184 185bool 186SyncSampleAtom::IsSyncSample(uint32 sampleNum) const 187{ 188 for (int32 count = 0; count < (int32)_entryCount; count++) 189 { 190 if ((_psampleNumbers[count] - 1) == sampleNum) 191 { 192 return true; 193 } 194 } 195 196 return false; 197} 198 199 200