|
23 | 23 | #include <cerrno> |
24 | 24 | #include <cstdio> |
25 | 25 | #include <sys/stat.h> |
| 26 | +#include "util/rsdebug.h" |
26 | 27 |
|
27 | 28 | #include "ftfilecreator.h" |
28 | 29 | #include "util/rstime.h" |
|
49 | 50 | ***********************************************************/ |
50 | 51 |
|
51 | 52 | ftFileCreator::ftFileCreator(const std::string& path, uint64_t size, const RsFileHash& hash,bool assume_availability) |
52 | | - : ftFileProvider(path,size,hash), chunkMap(size,assume_availability) |
| 53 | + : ftFileProvider(path,size,hash), chunkMap(size,assume_availability), _mp4_index_found(false), _mp4_index_offset(0) |
53 | 54 | { |
| 55 | + RsDbg() << "STREAMING: ftFileCreator CONSTRUCTOR for " << path; |
54 | 56 | /* |
55 | 57 | * FIXME any inits to do? |
56 | 58 | */ |
@@ -239,6 +241,13 @@ bool ftFileCreator::addFileData(uint64_t offset, uint32_t chunk_size, void *data |
239 | 241 | * Notify ftFileChunker about chunks received |
240 | 242 | */ |
241 | 243 | locked_notifyReceived(offset,chunk_size); |
| 244 | + |
| 245 | + // MP4 Smart Preview hook |
| 246 | + RsDbg() << "STREAMING: addFileData offset=" << offset << " strat=" << chunkMap.getStrategy(); |
| 247 | + if (!_mp4_index_found) |
| 248 | + { |
| 249 | + checkForMp4Index(); |
| 250 | + } |
242 | 251 |
|
243 | 252 | complete = chunkMap.isComplete(); |
244 | 253 | } |
@@ -497,15 +506,16 @@ void ftFileCreator::setChunkStrategy(FileChunksInfo::ChunkStrategy s) |
497 | 506 | RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ |
498 | 507 |
|
499 | 508 | // Let's check, for safety. |
500 | | - if(s != FileChunksInfo::CHUNK_STRATEGY_STREAMING && s != FileChunksInfo::CHUNK_STRATEGY_RANDOM && s != FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) |
| 509 | + if(s != FileChunksInfo::CHUNK_STRATEGY_SEQUENTIAL && s != FileChunksInfo::CHUNK_STRATEGY_RANDOM && s != FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE && s != FileChunksInfo::CHUNK_STRATEGY_STREAMING) |
501 | 510 | { |
502 | | - std::cerr << "ftFileCreator::ERROR: invalid chunk strategy " << s << "!" << " setting default value " << FileChunksInfo::CHUNK_STRATEGY_STREAMING << std::endl ; |
| 511 | + std::cerr << "ftFileCreator::ERROR: invalid chunk strategy " << s << "!" << " setting default value " << FileChunksInfo::CHUNK_STRATEGY_SEQUENTIAL << std::endl ; |
503 | 512 | s = FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE ; |
504 | 513 | } |
505 | 514 |
|
506 | 515 | #ifdef FILE_DEBUG |
507 | 516 | std::cerr << "ftFileCtreator: setting chunk strategy to " << s << std::endl ; |
508 | 517 | #endif |
| 518 | + RsDbg() << "STREAMING: ftFileCreator::setChunkStrategy " << s; |
509 | 519 | chunkMap.setStrategy(s) ; |
510 | 520 | } |
511 | 521 |
|
@@ -761,5 +771,95 @@ bool ftFileCreator::verifyChunk(uint32_t chunk_number,const Sha1CheckSum& sum) |
761 | 771 | return true ; |
762 | 772 | } |
763 | 773 |
|
| 774 | +bool ftFileCreator::checkForMp4Index() |
| 775 | +{ |
| 776 | + int strat = (int)chunkMap.getStrategy(); |
| 777 | + |
| 778 | + // STRICT RULE: Only active in STREAMING_PRIO_END |
| 779 | + if (strat != FileChunksInfo::CHUNK_STRATEGY_STREAMING) |
| 780 | + { |
| 781 | + // RsDbg() << "STREAMING: ftFileCreator::checkForMp4Index ignored. Strategy=" << strat; |
| 782 | + return false; |
| 783 | + } |
| 784 | + |
| 785 | + // Phase 1: Just log that we passed the guard |
| 786 | + RsDbg() << "STREAMING: ftFileCreator::checkForMp4Index RUNNING. Strategy=" << strat << ". Parsing loop start."; |
| 787 | + |
| 788 | + // Phase 2: Atom Parsing (Observer Mode) |
| 789 | + if (_mp4_index_found) return true; |
| 790 | + |
| 791 | + // Open file to read atoms |
| 792 | + FILE* f = fopen(file_name.c_str(), "rb"); |
| 793 | + if (!f) |
| 794 | + { |
| 795 | + RsDbg() << "STREAMING: Failed to open file " << file_name; |
| 796 | + return false; |
| 797 | + } |
| 798 | + |
| 799 | + uint64_t currentPos = 0; |
| 800 | + |
| 801 | + // MP4 Atom Header |
| 802 | + struct { |
| 803 | + uint32_t size; |
| 804 | + char type[4]; |
| 805 | + } header; |
| 806 | + |
| 807 | + int safe_loop_count = 0; |
| 808 | + |
| 809 | + while (true) |
| 810 | + { |
| 811 | + if (fseek(f, currentPos, SEEK_SET) != 0 || fread(&header, 1, 8, f) != 8) |
| 812 | + break; |
| 813 | + |
| 814 | + uint32_t atomSize = be32toh(header.size); |
| 815 | + uint64_t realAtomSize = atomSize; |
| 816 | + |
| 817 | + if (atomSize == 1) { |
| 818 | + uint64_t bigSize; |
| 819 | + if (fread(&bigSize, 1, 8, f) == 8) realAtomSize = be64toh(bigSize); |
| 820 | + } |
| 821 | + |
| 822 | + // Create a null-terminated string for logging safely |
| 823 | + char typeStr[5] = {0}; |
| 824 | + memcpy(typeStr, header.type, 4); |
| 825 | + |
| 826 | + RsDbg() << "STREAMING: Found atom '" << typeStr << "' at " << currentPos << " size " << realAtomSize; |
| 827 | + |
| 828 | + if (strncmp(header.type, "moov", 4) == 0) { |
| 829 | + RsDbg() << "STREAMING: MOOV atom found at " << currentPos << " (Beginning of file?). Stop."; |
| 830 | + _mp4_index_found = true; |
| 831 | + break; |
| 832 | + } |
| 833 | + |
| 834 | + if (strncmp(header.type, "mdat", 4) == 0) { |
| 835 | + uint64_t predictedMoov = currentPos + realAtomSize; |
| 836 | + RsDbg() << "STREAMING: MDAT found. Size: " << realAtomSize << ". Predicted MOOV at: " << predictedMoov; |
| 837 | + |
| 838 | + // Phase 3: Actuation |
| 839 | + // Calculate chunks covering the MOOV index (from predictedMoov to end of file) |
| 840 | + uint32_t chunkSize = ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE; |
| 841 | + uint32_t startChunk = predictedMoov / chunkSize; |
| 842 | + uint32_t endChunk = mSize / chunkSize; |
| 843 | + |
| 844 | + RsDbg() << "STREAMING: Setting High Priority Range: " << startChunk << " -> " << endChunk; |
| 845 | + chunkMap.setHighPriorityRange(startChunk, endChunk); |
| 846 | + |
| 847 | + _mp4_index_found = true; |
| 848 | + break; |
| 849 | + } |
| 850 | + |
| 851 | + currentPos += realAtomSize; |
| 852 | + if (realAtomSize == 0 || currentPos >= mSize) break; |
| 853 | + |
| 854 | + if (++safe_loop_count > 50) { |
| 855 | + RsDbg() << "STREAMING: Safety break (too many atoms)"; |
| 856 | + break; |
| 857 | + } |
| 858 | + } |
| 859 | + |
| 860 | + fclose(f); |
| 861 | + return false; |
| 862 | +} |
| 863 | + |
764 | 864 |
|
765 | 865 |
|
0 commit comments