Uszkodzenie danych podczas odczytu w czasie rzeczywistym wyjścia H.264 z AVAssetWriter

Używam kilku sztuczek, aby spróbować odczytać surowe wyjście AVAssetWriter podczas jego zapisywania na dysk. Kiedy składam poszczególne pliki, łącząc je, wynikowy plik ma taką samą liczbę bajtów, jak plik wyjściowy AVAssetWriter. Jednak ponownie złożony plik nie będzie odtwarzany w QuickTime ani nie będzie analizowany przez FFmpeg, ponieważ występuje uszkodzenie danych. Kilka bajtów tu i tam zostało zmienionych, co powoduje, że wynikowy plik jest bezużyteczny. Zakładam, że dzieje się to na granicy EOF każdego odczytu, ale nie jest to spójne uszkodzenie.

Zamierzam ostatecznie użyć kodu podobnego do tego, aby przeanalizować poszczególne jednostki NAL H.264 z kodera, aby je spakować i wysłać przez RTP, jednak jeśli nie mogę ufać odczytanym danym z dysku, być może będę musiał użyć innego rozwiązania .

Czy istnieje wyjaśnienie / poprawka w przypadku uszkodzenia danych? Czy są jakieś inne zasoby / linki, które znaleźliście, w jaki sposób analizować jednostki NAL, aby spakować za pomocą RTP?

Pełny kod tutaj:AVAppleEncoder.m

// Modified from
// http://www.davidhamrick.com/2011/10/13/Monitoring-Files-With-GCD-Being-Edited-With-A-Text-Editor.html
- (void)watchOutputFileHandle
{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    int fildes = open([[movieURL path] UTF8String], O_EVTONLY);

    source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE,fildes,
                                                              DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_ATTRIB | DISPATCH_VNODE_LINK | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_REVOKE,
                                                              queue);
    dispatch_source_set_event_handler(source, ^
                                      {
                                          unsigned long flags = dispatch_source_get_data(source);
                                          if(flags & DISPATCH_VNODE_DELETE)
                                          {
                                              dispatch_source_cancel(source);
                                              //[blockSelf watchStyleSheet:path];
                                          }
                                          if(flags & DISPATCH_VNODE_EXTEND)
                                          {
                                              //NSLog(@"File size changed");
                                              NSError *error = nil;
                                              NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingFromURL:movieURL error:&error];
                                              if (error) {
                                                  [self showError:error];
                                              }
                                              [fileHandle seekToFileOffset:fileOffset];
                                              NSData *newData = [fileHandle readDataToEndOfFile];
                                              if ([newData length] > 0) {
                                                  NSLog(@"newData (%lld): %d bytes", fileOffset, [newData length]);
                                                  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
                                                  NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
                                                  NSString *movieName = [NSString stringWithFormat:@"%d.%lld.%d.mp4", fileNumber, fileOffset, [newData length]];
                                                  NSString *path = [NSString stringWithFormat:@"%@/%@", basePath, movieName];
                                                  [newData writeToFile:path atomically:NO];
                                                  fileNumber++;
                                                  fileOffset = [fileHandle offsetInFile];
                                              }
                                          }
                                      });
    dispatch_source_set_cancel_handler(source, ^(void) 
                                       {
                                           close(fildes);
                                       });
    dispatch_resume(source);
}

Oto kilka podobnych pytań, które znalazłem, ale nie odpowiadam dokładnie na moje pytanie:

Uzyskaj PTS z surowego mdat H264 wygenerowanego przez iOS AVAssetWriterprzesyłanie strumieniowe wideo z iPhone'aPrzetwarzanie jednostek h.264 NAL z quicktime MOVPrzesyłanie strumieniowe audio / wideo w czasie rzeczywistym z iPhone'a do innego urządzenia (przeglądarki lub iPhone'a)

Kiedy w końcu to zrozumiem, wydam bibliotekę open source, aby pomóc ludziom, którzy próbują to zrobić w przyszłości.

Dziękuję Ci!

Aktualizacja: Korupcja nie ma miejsca na granicy EOF. Wygląda na to, że części pliku są ponownie zapisywane pofinishWriting jest nazywany. Ten pierwszy plik został podzielony na 4 KB, więc zmieniony obszar nie znajduje się w pobliżu granicy EOF. Wygląda na to, że jest uszkodzony również w pobliżu nowych elementów „moov”movieFragmentInterval jest włączony.

 Poprawny plik po lewej, uszkodzony plik po prawej stronie.

questionAnswers(2)

yourAnswerToTheQuestion