Changeset 368 for dsfilters/demux_mpc/src/mpc_file.cpp
- Timestamp:
- 12/14/07 00:22:01 (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
dsfilters/demux_mpc/src/mpc_file.cpp
r367 r368 19 19 duration_10mhz(0), 20 20 reader(NULL), 21 packet(NULL),22 21 seek_table(NULL), 23 22 seek_table_position(0) 24 23 { 25 key = 0; 26 packet_max_size = 512 * 1024; // well. hard to say. but I think this should be enough 27 packet_size = 0; 28 packet = (uint8*)malloc(packet_max_size); 29 30 ASSERT(packet); 24 extradata_max_size = 16*1024; // way too much.. 25 extradata_size = 0; 26 extradata = (uint8*)malloc(extradata_max_size); 31 27 } 32 28 33 29 CMPCFile::~CMPCFile() 34 30 { 35 if (seek_table) { 36 free(seek_table); 37 seek_table = NULL; 38 } 39 if (packet) { 40 free(packet); 41 packet = NULL; 42 } 31 if (seek_table) { free(seek_table); seek_table = NULL; } 32 if (extradata) { free(extradata); extradata = NULL; } 43 33 } 44 34 … … 52 42 // keep a local copy of the reader 53 43 this->reader = reader; 54 55 44 56 45 // According to stream specification the first 4 bytes should be 'MPCK' … … 70 59 71 60 // now loop through a few packets 61 CMPCPacket packet; 72 62 do { 73 ret = ReadNextPacket();63 ret = packet.Load(reader); 74 64 if (ret < 0) return -1; // end of file reached before initialization is done ? 75 65 76 switch (key) { 77 case MPC_KEY('S','H'): ret = ReadStreamHeader(); break; 78 case MPC_KEY('R','G'): ret = ReadReplaygain(); break; 79 case MPC_KEY('S','O'): ret = ReadSeekOffset(); break; 66 switch (packet.key) { 67 case MPC_KEY('S','H'): 68 ret = ReadStreamHeader(&packet); 69 StoreExtraDataPacket(&packet); 70 break; 71 case MPC_KEY('R','G'): 72 ret = ReadReplaygain(&packet); 73 StoreExtraDataPacket(&packet); 74 break; 75 case MPC_KEY('S','O'): 76 ret = ReadSeekOffset(&packet); 77 break; 78 case MPC_KEY('E','I'): 79 StoreExtraDataPacket(&packet); 80 break; 80 81 81 82 // audio packet - initialization is over … … 89 90 // if there was a seek table, load it 90 91 if (seek_table_position != 0) { 91 ret = ReadSeekTable(); 92 int64 first_ap_pos, avail; 93 reader->GetPosition(&first_ap_pos, &avail); 94 95 reader->Seek(seek_table_position); 96 ret = packet.Load(reader); 97 ret = ReadSeekTable(&packet); 92 98 if (ret < 0) return ret; 93 } 94 95 return 0; 96 } 97 98 int CMPCFile::ReadNextPacket() 99 { 100 uint16 key_val; 101 int64 size_val; 102 int32 size_len; 103 int ret; 104 int64 avail; 105 106 reader->GetPosition(&packet_pos, &avail); 107 ret = reader->GetKey(key_val); if (ret < 0) return ret; 108 ret = reader->GetSizeElm(size_val, size_len); if (ret < 0) return ret; 109 110 // if the key is not valid, quit 111 if (!reader->KeyValid(key_val)) return -1; 112 key = key_val; 113 114 // size_val is the total size including key, variable size field and payload 115 packet_size = size_val - 2 - size_len; 116 ASSERT(packet_size <= packet_max_size); 117 118 ret = reader->Read(packet, packet_size); if (ret < 0) return ret; 119 return 0; 99 100 // seek back to first AP 101 reader->Seek(first_ap_pos); 102 } 103 104 // we're at start 105 current_sample = 0; 106 return 0; 107 } 108 109 void CMPCFile::StoreExtraDataPacket(CMPCPacket *packet) 110 { 111 // we add current packet to extradata 112 uint8 *out = extradata + extradata_size; 113 memcpy(out, packet->packet, packet->packet_size); 114 extradata_size += packet->packet_size; 120 115 } 121 116 122 117 // parsing packets 123 124 int CMPCFile::ReadReplaygain() 125 { 126 Bitstream b(packet); 118 int CMPCFile::ReadReplaygain(CMPCPacket *packet) 119 { 120 Bitstream b(packet->payload); 127 121 b.NeedBits(); 128 122 … … 139 133 } 140 134 141 int CMPCFile::ReadSeekOffset( )142 { 143 Bitstream b(packet );135 int CMPCFile::ReadSeekOffset(CMPCPacket *packet) 136 { 137 Bitstream b(packet->payload); 144 138 145 139 seek_table_position = b.GetMpcSize(); 146 seek_table_position += packet _pos;140 seek_table_position += packet->file_position; 147 141 148 142 // success … … 150 144 } 151 145 152 int CMPCFile::ReadSeekTable() 153 { 154 reader->Seek(seek_table_position); 155 int ret; 156 157 ret = ReadNextPacket(); 158 if (ret < 0) return ret; 159 160 Bitstream b(packet); 146 int CMPCFile::ReadSeekTable(CMPCPacket *packet) 147 { 148 Bitstream b(packet->payload); 161 149 162 150 // calculate size as seen in mpc_demux.c 163 151 int64 tmp = b.GetMpcSize(); b.NeedBits(); 164 152 seek_table_size = tmp; 165 intseek_pwr = block_pwr + b.UGetBits(4);153 seek_pwr = block_pwr + b.UGetBits(4); 166 154 tmp = 2+total_samples / (1152 << seek_pwr); 167 155 if (tmp < seek_table_size) tmp = seek_table_size; … … 188 176 } 189 177 190 int CMPCFile::ReadStreamHeader( )191 { 192 Bitstream b(packet );178 int CMPCFile::ReadStreamHeader(CMPCPacket *packet) 179 { 180 Bitstream b(packet->payload); 193 181 b.NeedBits(); 194 182 … … 249 237 250 238 // store absolute position of stream header 251 header_position = packet _pos;239 header_position = packet->file_position -4; 252 240 } 253 241 break; … … 261 249 } 262 250 263 251 // parsing out packets 252 int CMPCFile::ReadAudioPacket(CMPCPacket *packet, int64 *cur_sample) 253 { 254 // we just load packets until we face the SE packet. Then we return -1 255 int ret; 256 257 do { 258 ret = packet->Load(reader); 259 if (ret < 0) return ret; 260 261 switch (packet->key) { 262 case MPC_KEY('A','P'): 263 { 264 // keep track of samples... 265 if (cur_sample) *cur_sample = current_sample; 266 current_sample += (1152*audio_block_frames); 267 268 return 0; // we got one 269 } 270 case MPC_KEY('S','E'): return -1; // end of stream 271 } 272 273 // skip other packets 274 } while (1); 275 276 // unexpected... 277 return 0; 278 } 279 280 int CMPCFile::Seek(int64 seek_sample) 281 { 282 /* 283 This will be a little tricky. I would like to support also 284 less precise seeking with files that don't have seeking table. 285 But if there is one, we would use that one. 286 287 Original implementation also deals with introductory silence. 288 But since I don't know of any dshow filters capable of 289 gapless playback we would ignore this. Of course it can 290 be implemented later. 291 292 It is absolutely okay to do AP-level seeking. The caller 293 knows the exact time it wants to seek to and we will provide 294 the nearest AP. If the requested time is in the middle of AP, 295 the (current_time - requested_time) expression would be negative 296 and decoder will skip samples until positive time values are encountered. 297 This way we can do sample-precise seeking. 298 */ 299 300 // cannot seek 301 if (seek_table == NULL || seek_table_size == 0) return -1; 302 303 int packet_num = seek_sample / (1152*audio_block_frames); 304 int i = (packet_num >> (seek_pwr - block_pwr)); 305 if (i >= seek_table_size) { 306 i = seek_table_size-1; 307 } 308 309 // seek to position 310 uint32 pos = seek_table[i] >> 3; 311 reader->Seek(pos); 312 313 // shift back 314 i = i << (seek_pwr - block_pwr); 315 current_sample = i*audio_block_frames; 316 317 return 0; 318 } 319 320 321 //----------------------------------------------------------------------------- 322 // 323 // CMPCPacket 324 // 325 //----------------------------------------------------------------------------- 326 327 CMPCPacket::CMPCPacket() : 328 file_position(0), 329 packet(NULL), 330 payload(NULL), 331 packet_size(0), 332 payload_size(0), 333 key(0) 334 { 335 } 336 337 CMPCPacket::~CMPCPacket() 338 { 339 // just let it go 340 Release(); 341 } 342 343 void CMPCPacket::Release() 344 { 345 if (packet) { free(packet); packet = NULL; } 346 payload = NULL; 347 packet_size = 0; 348 payload_size = 0; 349 key = 0; 350 file_position = 0; 351 } 352 353 int CMPCPacket::Load(CMPCReader *reader) 354 { 355 uint16 key_val; 356 int64 size_val, avail; 357 int32 size_len; 358 int ret; 359 Release(); 360 reader->GetPosition(&file_position, &avail); 361 362 // end of stream 363 if (file_position >= avail) return -1; 364 365 ret = reader->GetKey(key_val); if (ret < 0) return ret; 366 ret = reader->GetSizeElm(size_val, size_len); if (ret < 0) return ret; 367 // if the key is not valid, quit 368 if (!reader->KeyValid(key_val)) return -1; 369 key = key_val; 370 371 // now load the packet 372 packet_size = size_val; 373 payload_size = size_val - 2 - size_len; 374 packet = (uint8*)malloc(packet_size); 375 payload = packet + 2 + size_len; // pointer to packet payload 376 377 // roll back the bytes 378 reader->Seek(file_position); 379 ret = reader->Read(packet, packet_size); if (ret < 0) return ret; 380 381 return 0; 382 } 383 384
Note: See TracChangeset
for help on using the changeset viewer.