Chciałem napisać program, który zrobi mi drzewo tagów w pliku mov. Częściowo działa, ale nie wiem czemu czasami się gubi. Znajduje część tagów, a w którymś chyba jest źle policzone przesunięcie w pliku i wychodzą głupoty. Proszę o pomoc. Kod źródłowy z XCode:
// // main.m // ReadMOVAtoms // // Created by Damian Dudycz on 04.02.2015. // Copyright (c) 2015 Damian Dudycz. All rights reserved. // #import <Foundation/Foundation.h> #import <stdio.h> #define ATOM_TYPE_FTYP 1718909296 #define ATOM_TYPE_MOOV 1836019574 #define ATOM_TYPE_WIDE 2003395685 #define ATOM_TYPE_MDAT 1835295092 @interface AtomReader : NSObject { long fileSize; } - (void)perform; @end @implementation AtomReader // Funkcja wyszukuje atomy pomiędzy podanymi pozycjami w pliku. - (NSArray *)rootAtomsInFile:(FILE *)movFile from:(UInt64)startPosition to:(UInt64)endPosition { // Przesuń wskaźnij na początek przedziału. fseek(movFile, startPosition, SEEK_SET); // Rozmiar przeszukiwanego przedziału UInt64 spaceLength = endPosition - startPosition; // Ilość pozostałych do przeczytania w przedziale bajtów int64_t bytesLeft = spaceLength; // Pozycja wskaźnika względem pliku i względem początku przedziału UInt64 currentPosInFile = startPosition; UInt64 atomPositionInFile; // Bufor dla wczytywania pliku char buffer[1000]; // Wyniki NSMutableArray *atoms = [NSMutableArray arrayWithCapacity:10]; while (bytesLeft > 0) { atomPositionInFile = currentPosInFile; size_t bytesRead; // Get atom size bytesRead = fread(buffer, 1, 4, movFile); //bytesLeft -= bytesRead; UInt32 atomSize1 = 0; for (unsigned n = 0; n < sizeof(atomSize1); ++n) { atomSize1 = (atomSize1 << 8) + buffer[n]; } // Get atom type bytesRead = fread(buffer, 1, 4, movFile); //bytesLeft -= bytesRead; NSMutableString *atomName = [NSMutableString stringWithCapacity:4]; UInt32 atomType = 0; for (short n = 0; n < sizeof(atomType); ++n) { atomType = (atomType << 8) + buffer[n]; [atomName appendFormat:@"%c", buffer[n]]; } UInt64 atomDataOffset = 8; // If atom size is equal to 1, get 64bit atom size UInt64 trueAtomSize = atomSize1; UInt64 atomSize2 = 0; if (atomSize1 == 1) { bytesRead = fread(buffer, 1, 8, movFile); //bytesLeft -= bytesRead; for (short n = 0; n < sizeof(atomSize2); ++n) { atomSize2 = (atomSize2 << 8) + buffer[n]; } trueAtomSize = atomSize2; atomDataOffset = 16; } if (trueAtomSize == 0) { trueAtomSize = fileSize - atomPositionInFile; } // Przesuń wskaźnik o resztę atomu currentPosInFile = trueAtomSize + atomPositionInFile; fseek(movFile, currentPosInFile, SEEK_SET); bytesLeft -= trueAtomSize; NSNumber *atomSizeNumber = @(trueAtomSize); [atoms addObject:@{@"TYPE" : atomName, @"SIZE" : atomSizeNumber}]; if (atomType == ATOM_TYPE_MOOV) { UInt64 start = atomPositionInFile + atomDataOffset; UInt64 end = atomPositionInFile + trueAtomSize; [atoms addObject:[self rootAtomsInFile:movFile from:start to:end]]; } fseek(movFile, currentPosInFile, SEEK_SET); } return atoms; } - (void)perform { FILE *file = fopen("/Users/damiandudycz/Desktop/Movie.mov", "rb"); assert(file != nil); fseek(file, 0, SEEK_END); fileSize = ftell(file); fseek(file, 0, SEEK_SET); NSArray *atoms = [self rootAtomsInFile:file from:0 to:fileSize]; NSLog(@"%@", atoms); fclose(file); } @end int main(int argc, const char * argv[]) { @autoreleasepool { AtomReader *reader = [[AtomReader alloc] init]; [reader perform]; } return 0; }
Przykładowe wyjście:
( { SIZE = 20; TYPE = ftyp; }, { SIZE = 9240; TYPE = moov; }, ( { SIZE = 108; TYPE = mvhd; }, { SIZE = 7211; TYPE = trak; }, { SIZE = 1500; TYPE = trak; }, { SIZE = 3667779; TYPE = "9*\U2018"; } ), { SIZE = 8; TYPE = wide; }, { SIZE = 4927064; TYPE = mdat; } )
Część tagów jest ok, ale pojawia się ten 9*\U2018 nie wiadomo skąd. Poza tym czasami są źle wyciągnięte rozmiary atomów.
Użytkownik oneghost edytował ten post 05 lutego 2015 - 13:44