Browse Source

bugfix: 重写box解析部分

wubin1993 4 years ago
parent
commit
f6575b9554

+ 1 - 1
QGVAPlayer.podspec

@@ -16,7 +16,7 @@ Pod::Spec.new do |spec|
   #
   #
 
 
   spec.name         = "QGVAPlayer"
   spec.name         = "QGVAPlayer"
-  spec.version      = "1.0.16"
+  spec.version      = "1.0.17"
   spec.summary      = "video animation player."
   spec.summary      = "video animation player."
   spec.platform     = :ios, "8.0"
   spec.platform     = :ios, "8.0"
 
 

+ 6 - 0
iOS/CHANGELOG.md

@@ -1,3 +1,9 @@
+## iOS 1.0.17
+
+**bugfix**
+
+- 修复mp4解析length异常。
+
 ## iOS 1.0.16
 ## iOS 1.0.16
 
 
 **bugfix**
 **bugfix**

+ 53 - 49
iOS/QGVAPlayer/QGVAPlayer/Classes/MP4Parser/QGMP4Parser.m

@@ -78,35 +78,22 @@
         //第一个子box
         //第一个子box
         offset = calBox.superBox ? (calBox.startIndexInBytes + kQGBoxSizeLengthInBytes + kQGBoxTypeLengthInBytes) : 0;
         offset = calBox.superBox ? (calBox.startIndexInBytes + kQGBoxSizeLengthInBytes + kQGBoxTypeLengthInBytes) : 0;
         
         
-        //avcbox特殊处理
-        if (calBox.type == QGMP4BoxType_avc1 || calBox.type == QGMP4BoxType_hvc1 || calBox.type == QGMP4BoxType_stsd) {
-            unsigned long long avcOffset = calBox.startIndexInBytes+kQGBoxSizeLengthInBytes+kQGBoxTypeLengthInBytes;
-            unsigned long long avcEdge = calBox.startIndexInBytes+calBox.length-kQGBoxSizeLengthInBytes-kQGBoxTypeLengthInBytes;
-            unsigned long long avcLength = 0;
-            QGMP4BoxType avcType = QGMP4BoxType_unknown;
-            for (; avcOffset < avcEdge; avcOffset++) {
-                readBoxTypeAndLength(_fileHandle, avcOffset, &avcType, &avcLength);
-                if (avcType == QGMP4BoxType_avc1 || avcType == QGMP4BoxType_avcC || avcType == QGMP4BoxType_hvc1 || avcType == QGMP4BoxType_hvcC) {
-                    QGMP4Box *avcBox = [QGMP4BoxFactory createBoxForType:avcType startIndex:avcOffset length:avcLength];
-                    if (!calBox.subBoxes) {
-                        calBox.subBoxes = [NSMutableArray new];
-                    }
-                    [calBox.subBoxes addObject:avcBox];
-                    avcBox.superBox = calBox;
-                    [BFSQueue addObject:avcBox];
-                    offset = (avcBox.startIndexInBytes+avcBox.length);
-                    [self didParseBox:avcBox];
-                    break ;
-                }
-            }
+        //特殊处理
+        if ([self shouldResetOffset:calBox.type]) {
+            [self calibrateOffset:&offset boxType:calBox.type];
         }
         }
+        
+        //解析子box
         do {
         do {
             //判断是否会越界
             //判断是否会越界
             if ((offset+kQGBoxSizeLengthInBytes+kQGBoxTypeLengthInBytes)>(calBox.startIndexInBytes+calBox.length)) {
             if ((offset+kQGBoxSizeLengthInBytes+kQGBoxTypeLengthInBytes)>(calBox.startIndexInBytes+calBox.length)) {
                 break ;
                 break ;
             }
             }
-            readBoxTypeAndLength(_fileHandle, offset, &type, &length);
             
             
+            if (![self readBoxTypeAndLength:offset type:&type length:&length]) {
+                break;
+            }
+          
             if ((offset+length)>(calBox.startIndexInBytes+calBox.length)) {
             if ((offset+length)>(calBox.startIndexInBytes+calBox.length)) {
                 //reach to super box end or not a box
                 //reach to super box end or not a box
                 break ;
                 break ;
@@ -136,6 +123,50 @@
     [self didFinisheParseFile];
     [self didFinisheParseFile];
 }
 }
 
 
+- (BOOL)readBoxTypeAndLength:(uint64_t)offset type:(QGMP4BoxType *)type length:(uint64_t*)length {
+    [_fileHandle seekToFileOffset:offset];
+    NSData *data = [_fileHandle readDataOfLength:(kQGBoxSizeLengthInBytes + kQGBoxTypeLengthInBytes)];
+    if (data.length < kQGBoxSizeLengthInBytes + kQGBoxTypeLengthInBytes) {
+      VAP_Error(kQGVAPModuleCommon, @"read box length and type error");
+      return NO;
+    }
+    const char *bytes = data.bytes;
+    *length = [self readValue:bytes length:kQGBoxSizeLengthInBytes];
+    *type = [self readValue:&bytes[kQGBoxSizeLengthInBytes] length:kQGBoxTypeLengthInBytes];
+    if (*length == kQGBoxLargeSizeFlagLengthInBytes) {
+      offset += kQGBoxSizeLengthInBytes + kQGBoxTypeLengthInBytes;
+      [_fileHandle seekToFileOffset:offset];
+      data = [_fileHandle readDataOfLength:kQGBoxLargeSizeLengthInBytes];
+      if (data.length < kQGBoxLargeSizeLengthInBytes) {
+        VAP_Error(kQGVAPModuleCommon, @"read box length and type error");
+        return NO;
+      }
+      bytes = data.bytes;
+      *length = [self readValue:bytes length:kQGBoxLargeSizeLengthInBytes];
+    }
+    return YES;
+}
+
+- (BOOL)shouldResetOffset:(QGMP4BoxType)type {
+    return type == QGMP4BoxType_stsd ||
+           type == QGMP4BoxType_avc1 ||
+           type == QGMP4BoxType_hvc1;
+}
+
+- (void)calibrateOffset:(uint64_t*)offset boxType:(QGMP4BoxType)type {
+    switch (type) {
+        case QGMP4BoxType_stsd:
+            *offset += 8;
+            break;
+        case QGMP4BoxType_avc1:
+        case QGMP4BoxType_hvc1:
+            *offset += (24 + 2 + 2 + 14 + 32 + 4);
+            break;
+        default:
+            break;
+    }
+}
+
 - (NSData *)readDataForBox:(QGMP4Box *)box {
 - (NSData *)readDataForBox:(QGMP4Box *)box {
     
     
     if (!box) {
     if (!box) {
@@ -173,33 +204,6 @@
     }
     }
 }
 }
 
 
-unsigned long long dataConvertToUInt64(NSData *data) {
-    
-    unsigned long long largeSize = 0;
-    if (data.length < 8) {
-        return largeSize;
-    }
-    const char *bytes = data.bytes;
-    for (int i = 0; i < 8; i++) {
-        largeSize += ((bytes[i]&0xff) << (8 - i - 1) * 8);
-    }
-    return largeSize;
-}
-
-void readBoxTypeAndLength(NSFileHandle *fileHandle, unsigned long long offset, QGMP4BoxType *type, unsigned long long *length) {
-    
-    [fileHandle seekToFileOffset:offset];
-    NSData *data = [fileHandle readDataOfLength:kQGBoxSizeLengthInBytes+kQGBoxTypeLengthInBytes];
-    const char *bytes = data.bytes;
-    *length = ((bytes[0]&0xff)<<24)+((bytes[1]&0xff)<<16)+((bytes[2]&0xff)<<8)+(bytes[3]&0xff);
-    *type = ((bytes[4]&0xff)<<24)+((bytes[5]&0xff)<<16)+((bytes[6]&0xff)<<8)+(bytes[7]&0xff);
-    if (*length == kQGBoxLargeSizeFlagLengthInBytes) {
-        [fileHandle seekToFileOffset:offset + kQGBoxSizeLengthInBytes + kQGBoxTypeLengthInBytes];
-        NSData *largeSizeData = [fileHandle readDataOfLength:kQGBoxLargeSizeLengthInBytes];
-        *length = dataConvertToUInt64(largeSizeData);
-    }
-}
-
 @end
 @end
 
 
 #pragma mark - parser proxy
 #pragma mark - parser proxy

+ 1 - 1
iOS/QGVAPlayerDemo/QGVAPlayerDemo/ViewController.m

@@ -107,7 +107,7 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
     //指定素材混合模式,重复播放次数,delegate的接口
     //指定素材混合模式,重复播放次数,delegate的接口
     
     
     //注意若素材不含vapc box,则必须用调用如下接口设置enable才可播放
     //注意若素材不含vapc box,则必须用调用如下接口设置enable才可播放
-    //[mp4View enableOldVersion:YES];
+    [mp4View enableOldVersion:YES];
     [mp4View playHWDMP4:resPath repeatCount:-1 delegate:self];
     [mp4View playHWDMP4:resPath repeatCount:-1 delegate:self];
 }
 }