From 29669f24c4758c6df6d3a134399841a4bb7fffc2 Mon Sep 17 00:00:00 2001
From: Thulinma <jaron@vietors.com>
Date: Tue, 31 Jan 2017 14:48:49 +0100
Subject: [PATCH] MP4 speed optimize

---
 lib/mp4.cpp                           | 34 ++++++++++++---------------
 lib/mp4.h                             |  3 ++-
 lib/mp4_generic.cpp                   |  5 ++--
 lib/mp4_generic.h                     |  2 +-
 src/output/output_progressive_mp4.cpp |  2 +-
 5 files changed, 22 insertions(+), 24 deletions(-)

diff --git a/lib/mp4.cpp b/lib/mp4.cpp
index 64c4a039..4c06aff7 100644
--- a/lib/mp4.cpp
+++ b/lib/mp4.cpp
@@ -84,25 +84,21 @@ namespace MP4 {
     return std::string(retVal + 4, 4);
   }
 
-  ///\todo make good working calcBoxSize with size and payloadoffset calculation
-  unsigned long int calcBoxSize(char readVal[16]) {
-    return (unsigned int)ntohl(((int *)readVal)[0]);
+  /// Checks box size, offset-aware
+  uint64_t calcBoxSize(const char * p){
+    uint64_t r = ntohl(((int *)p)[0]);
+    if (r == 1){
+      return (((uint64_t)ntohl(((int *)p)[2])) << 32) | ntohl(((int *)p)[3]);
+    }
+    return r;
   }
 
   bool skipBox(FILE * newData) {
     char readVal[16];
     long long unsigned int pos = ftell(newData);
-    if (fread(readVal, 4, 1, newData)) {
+    if (fread(readVal, 16, 1, newData)) {
       uint64_t size = calcBoxSize(readVal);
-      if (size == 1) {
-        if (fread(readVal + 4, 12, 1, newData)) {
-          size = 0 + ntohl(((int *)readVal)[2]);
-          size <<= 32;
-          size += ntohl(((int *)readVal)[3]);
-        } else {
-          return false;
-        }
-      } else if (size == 0) {
+      if (size == 0) {
         fseek(newData, 0, SEEK_END);
         return true;
       }
@@ -120,9 +116,9 @@ namespace MP4 {
   bool Box::read(FILE * newData) {
     char readVal[16];
     long long unsigned int pos = ftell(newData);
-    if (fread(readVal, 4, 1, newData)) {
+    if (fread(readVal, 16, 1, newData)) {
       payloadOffset = 8;
-      uint64_t size = calcBoxSize(readVal);
+      uint64_t size = ntohl(((int *)readVal)[0]);
       if (size == 1) {
         if (fread(readVal + 4, 12, 1, newData)) {
           size = 0 + ntohl(((int *)readVal)[2]);
@@ -182,7 +178,7 @@ namespace MP4 {
   /// Returns the total boxed size of this box, including the header.
   uint64_t Box::boxedSize() {
     if (payloadOffset == 16) {
-      return ((uint64_t)ntohl(((int *)data)[2]) << 32) + ntohl(((int *)data)[3]);
+      return ((uint64_t)ntohl(((int *)data)[2]) << 32) | ntohl(((int *)data)[3]);
     }
     return ntohl(((int *)data)[0]);
   }
@@ -621,7 +617,7 @@ namespace MP4 {
     if ((index + payloadOffset + 8) > boxedSize()) {
       return 0;
     }
-    return getBox(index).boxedSize();
+    return calcBoxSize(data + index + payloadOffset);
   }
 
   /// Replaces the existing box at the given index by the new box newEntry.
@@ -732,9 +728,9 @@ namespace MP4 {
     setBox(newContent, tempLoc);
   }
 
-  Box & containerBox::getContent(uint32_t no) {
+  Box & containerBox::getContent(uint32_t no, bool unsafe) {
     static Box ret = Box((char *)"\000\000\000\010erro", false);
-    if (no > getContentCount()) {
+    if (!unsafe && no > getContentCount()) {
       return ret;
     }
     unsigned int i = 0;
diff --git a/lib/mp4.h b/lib/mp4.h
index adf3863e..4b18fc57 100644
--- a/lib/mp4.h
+++ b/lib/mp4.h
@@ -17,6 +17,7 @@
 namespace MP4 {
   std::string readBoxType(FILE * newData);
   bool skipBox(FILE * newData);
+  uint64_t calcBoxSize(const char * p);
 
 
   class Box {
@@ -81,7 +82,7 @@ namespace MP4 {
       containerBox();
       uint32_t getContentCount();
       void setContent(Box & newContent, uint32_t no);
-      Box & getContent(uint32_t no);
+      Box & getContent(uint32_t no, bool unsafe = false);
       std::string toPrettyString(uint32_t indent = 0);
   };
 
diff --git a/lib/mp4_generic.cpp b/lib/mp4_generic.cpp
index e37c6748..878b9280 100644
--- a/lib/mp4_generic.cpp
+++ b/lib/mp4_generic.cpp
@@ -58,9 +58,10 @@ namespace MP4 {
     setBox(newContent, tempLoc);
   }
 
-  Box & TRAF::getContent(uint32_t no) {
+  /// Gets a reference to the given box number. If unsafe, doesn't check boundaries (getContentCount check skipped).
+  Box & TRAF::getContent(uint32_t no, bool unsafe) {
     static Box ret = Box((char *)"\000\000\000\010erro", false);
-    if (no > getContentCount()) {
+    if (!unsafe && no > getContentCount()) {
       return ret;
     }
     unsigned int i = 0;
diff --git a/lib/mp4_generic.h b/lib/mp4_generic.h
index a31e749e..c89bb7ac 100644
--- a/lib/mp4_generic.h
+++ b/lib/mp4_generic.h
@@ -21,7 +21,7 @@ namespace MP4 {
       TRAF();
       uint32_t getContentCount();
       void setContent(Box & newContent, uint32_t no);
-      Box & getContent(uint32_t no);
+      Box & getContent(uint32_t no, bool unsafe = false);
       std::string toPrettyString(uint32_t indent = 0);
   };
   //TRAF Box
diff --git a/src/output/output_progressive_mp4.cpp b/src/output/output_progressive_mp4.cpp
index c3ec0945..80e91809 100644
--- a/src/output/output_progressive_mp4.cpp
+++ b/src/output/output_progressive_mp4.cpp
@@ -542,7 +542,7 @@ namespace Mist {
     char * dataPointer = 0;
     unsigned int len = 0;
     thisPacket.getString("data", dataPointer, len);
-    if ((unsigned long)thisPacket.getTrackId() != sortSet.begin()->trackID || thisPacket.getTime() != sortSet.begin()->time){
+    if ((unsigned long)thisPacket.getTrackId() != sortSet.begin()->trackID || thisPacket.getTime() != sortSet.begin()->time || len != sortSet.begin()->size) {
       if (thisPacket.getTime() > sortSet.begin()->time || (unsigned long)thisPacket.getTrackId() > sortSet.begin()->trackID) {
         if (perfect){
           DEBUG_MSG(DLVL_WARN, "Warning: input is inconsistent. Expected %lu:%llu but got %ld:%llu - cancelling playback", sortSet.begin()->trackID, sortSet.begin()->time, thisPacket.getTrackId(), thisPacket.getTime());