should work with hevc/fmp4/cbcs

This commit is contained in:
Gilles Boccon-Gibod
2017-10-01 19:00:47 -07:00
parent 2fe0cb251d
commit ff8e005108
11 changed files with 717 additions and 74 deletions

View File

@@ -142,6 +142,8 @@
CA86EED219A95C68008A3B00 /* Ap4SegmentBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = CA86EED019A95C68008A3B00 /* Ap4SegmentBuilder.h */; };
CA86EEE219A95DFF008A3B00 /* libBento4.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAA7E6C914ACD763008AA54E /* libBento4.a */; };
CA86EEE519A95E30008A3B00 /* FragmentCreatorTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CA86EEE419A95E30008A3B00 /* FragmentCreatorTest.cpp */; };
CA87B94A1F81B0C4005F42D6 /* libBento4.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAA7E6C914ACD763008AA54E /* libBento4.a */; };
CA87B94D1F81B130005F42D6 /* Mp4Diff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CA87B94C1F81B122005F42D6 /* Mp4Diff.cpp */; };
CA8A94D91929A68700836179 /* libBento4.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAA7E6C914ACD763008AA54E /* libBento4.a */; };
CA8A94DC1929A6C100836179 /* Mp4Mux.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CA8A94DB1929A6C100836179 /* Mp4Mux.cpp */; };
CA8A94DD1929DD9100836179 /* Ap4AvcParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CA3EDA960D7E14D3007AE943 /* Ap4AvcParser.cpp */; };
@@ -970,6 +972,15 @@
);
runOnlyForDeploymentPostprocessing = 1;
};
CA87B9401F81B08B005F42D6 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
CAFE9C671D1B487700F9FF67 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -1067,6 +1078,9 @@
CA86EED019A95C68008A3B00 /* Ap4SegmentBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Ap4SegmentBuilder.h; sourceTree = "<group>"; };
CA86EED719A95DD3008A3B00 /* FragmentCreatorTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = FragmentCreatorTest; sourceTree = BUILT_PRODUCTS_DIR; };
CA86EEE419A95E30008A3B00 /* FragmentCreatorTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FragmentCreatorTest.cpp; sourceTree = "<group>"; };
CA87B9421F81B08B005F42D6 /* mp4diff */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mp4diff; sourceTree = BUILT_PRODUCTS_DIR; };
CA87B9441F81B08B005F42D6 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
CA87B94C1F81B122005F42D6 /* Mp4Diff.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mp4Diff.cpp; sourceTree = "<group>"; };
CA8A94CE1929A65E00836179 /* mp4mux */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mp4mux; sourceTree = BUILT_PRODUCTS_DIR; };
CA8A94DB1929A6C100836179 /* Mp4Mux.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mp4Mux.cpp; sourceTree = "<group>"; };
CA8B6A600F66D20900720A07 /* Ap4MfhdAtom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Ap4MfhdAtom.cpp; sourceTree = "<group>"; };
@@ -1492,6 +1506,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
CA87B93F1F81B08B005F42D6 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
CA87B94A1F81B0C4005F42D6 /* libBento4.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
CA8A94CB1929A65E00836179 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -1643,7 +1665,9 @@
CA646A860CE97B2D009699D7 /* Apps */,
CA646A9B0CE97B51009699D7 /* Test */,
C6A0FF2B0290797F04C91782 /* Documentation */,
CA87B9431F81B08B005F42D6 /* Mp4Diff */,
1AB674ADFE9D54B511CA2CBB /* Products */,
CA87B9491F81B0C4005F42D6 /* Frameworks */,
);
name = Bento4;
sourceTree = "<group>";
@@ -1705,6 +1729,7 @@
CA00A6531A1C36560064B4D3 /* mp4pssh */,
CAE1FBF61AF8493E00607B3C /* mp42hls */,
CAFE9C691D1B487700F9FF67 /* LargeFilesTest */,
CA87B9421F81B08B005F42D6 /* mp4diff */,
);
name = Products;
sourceTree = "<group>";
@@ -1790,6 +1815,7 @@
CA00CB8513D9F1EC00C1A140 /* Mp4Compact */,
CA44C5260D46371C00173F5F /* Mp4DcfPackager */,
CA646A8B0CE97B2D009699D7 /* Mp4Decrypt */,
CA87B94B1F81B122005F42D6 /* Mp4Diff */,
CA646A8D0CE97B2D009699D7 /* Mp4Dump */,
CA646A8F0CE97B2D009699D7 /* Mp4Edit */,
CA646A910CE97B2D009699D7 /* Mp4Encrypt */,
@@ -1935,6 +1961,29 @@
path = FragmentCreator;
sourceTree = "<group>";
};
CA87B9431F81B08B005F42D6 /* Mp4Diff */ = {
isa = PBXGroup;
children = (
CA87B9441F81B08B005F42D6 /* main.cpp */,
);
path = Mp4Diff;
sourceTree = "<group>";
};
CA87B9491F81B0C4005F42D6 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
CA87B94B1F81B122005F42D6 /* Mp4Diff */ = {
isa = PBXGroup;
children = (
CA87B94C1F81B122005F42D6 /* Mp4Diff.cpp */,
);
path = Mp4Diff;
sourceTree = "<group>";
};
CA8A94DA1929A6C100836179 /* Mp4Mux */ = {
isa = PBXGroup;
children = (
@@ -2903,6 +2952,23 @@
productReference = CA86EED719A95DD3008A3B00 /* FragmentCreatorTest */;
productType = "com.apple.product-type.tool";
};
CA87B9411F81B08B005F42D6 /* Mp4Diff */ = {
isa = PBXNativeTarget;
buildConfigurationList = CA87B9481F81B08B005F42D6 /* Build configuration list for PBXNativeTarget "Mp4Diff" */;
buildPhases = (
CA87B93E1F81B08B005F42D6 /* Sources */,
CA87B93F1F81B08B005F42D6 /* Frameworks */,
CA87B9401F81B08B005F42D6 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = Mp4Diff;
productName = Mp4Diff;
productReference = CA87B9421F81B08B005F42D6 /* mp4diff */;
productType = "com.apple.product-type.tool";
};
CA8A94CD1929A65E00836179 /* Mp4Mux */ = {
isa = PBXNativeTarget;
buildConfigurationList = CA8A94D61929A65E00836179 /* Build configuration list for PBXNativeTarget "Mp4Mux" */;
@@ -3223,6 +3289,10 @@
CA00A6521A1C36560064B4D3 = {
CreatedOnToolsVersion = 6.1;
};
CA87B9411F81B08B005F42D6 = {
CreatedOnToolsVersion = 9.0;
ProvisioningStyle = Manual;
};
CAFE9C681D1B487700F9FF67 = {
CreatedOnToolsVersion = 7.3;
};
@@ -3251,6 +3321,7 @@
F9FDDA2D0EA798FF0061DCB2 /* Bento4C */,
CA646ABA0CE97BFD009699D7 /* Mp4Dump */,
CA646ACD0CE97C80009699D7 /* Mp4Info */,
CA87B9411F81B08B005F42D6 /* Mp4Diff */,
CA646AE00CE97CD2009699D7 /* Mp4Encrypt */,
CA44C5290D46375F00173F5F /* Mp4DcfPackager */,
CA646AED0CE97CEE009699D7 /* Mp4Decrypt */,
@@ -3457,6 +3528,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
CA87B93E1F81B08B005F42D6 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CA87B94D1F81B130005F42D6 /* Mp4Diff.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
CA8A94CA1929A65E00836179 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -4700,6 +4779,73 @@
};
name = Release;
};
CA87B9461F81B08B005F42D6 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = mp4diff;
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = macosx;
};
name = Debug;
};
CA87B9471F81B08B005F42D6 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_NAME = mp4diff;
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = macosx;
};
name = Release;
};
CA8A94D41929A65E00836179 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -5466,6 +5612,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
CA87B9481F81B08B005F42D6 /* Build configuration list for PBXNativeTarget "Mp4Diff" */ = {
isa = XCConfigurationList;
buildConfigurations = (
CA87B9461F81B08B005F42D6 /* Debug */,
CA87B9471F81B08B005F42D6 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
CA8A94D61929A65E00836179 /* Build configuration list for PBXNativeTarget "Mp4Mux" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@@ -0,0 +1,231 @@
/*****************************************************************
|
| AP4 - MP4 File Info
|
| Copyright 2002-2015 Axiomatic Systems, LLC
|
|
| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
|
| Unless you have obtained Bento4 under a difference license,
| this version of Bento4 is Bento4|GPL.
| Bento4|GPL is free software; you can redistribute it and/or modify
| it under the terms of the GNU General Public License as published by
| the Free Software Foundation; either version 2, or (at your option)
| any later version.
|
| Bento4|GPL is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| GNU General Public License for more details.
|
| You should have received a copy of the GNU General Public License
| along with Bento4|GPL; see the file COPYING. If not, write to the
| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
| 02111-1307, USA.
|
****************************************************************/
/*----------------------------------------------------------------------
| includes
+---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include "Ap4.h"
#include "Ap4BitStream.h"
#include "Ap4Mp4AudioInfo.h"
#include "Ap4HevcParser.h"
/*----------------------------------------------------------------------
| constants
+---------------------------------------------------------------------*/
#define BANNER "MP4 Diff - Version 1.0.0\n"\
"(Bento4 Version " AP4_VERSION_STRING ")\n"\
"(c) 2002-2017 Axiomatic Systems, LLC"
/*----------------------------------------------------------------------
| globals
+---------------------------------------------------------------------*/
/*----------------------------------------------------------------------
| PrintUsageAndExit
+---------------------------------------------------------------------*/
static void
PrintUsageAndExit()
{
fprintf(stderr,
BANNER
"\n\nusage: mp4diff [options] <input1> <input2>\n"
);
exit(1);
}
/*----------------------------------------------------------------------
| DiffSamples
+---------------------------------------------------------------------*/
static void
DiffSamples(unsigned int index,
AP4_Sample& sample1, AP4_DataBuffer& sample_data1,
AP4_Sample& sample2, AP4_DataBuffer& sample_data2)
{
if (sample_data1.GetDataSize() != sample_data2.GetDataSize()) {
printf("!!! sample %d: sizes not equal: %d, %d\n", index, sample_data1.GetDataSize(), sample_data2.GetDataSize());
return;
}
const AP4_UI08* data1 = (const AP4_UI08*)sample_data1.GetData();
const AP4_UI08* data2 = (const AP4_UI08*)sample_data2.GetData();
bool in_diff = false;
unsigned int diff_start = 0;
for (unsigned int i=0; i<sample_data1.GetDataSize(); i++) {
if (in_diff) {
if (data1[i] == data2[i]) {
// end of diff
printf("!!! sample %d, %d differences at %d / %d\n", index, i-diff_start, diff_start, sample_data1.GetDataSize());
in_diff = false;
}
} else {
if (data1[i] != data2[i]) {
diff_start = i;
in_diff = true;
}
}
}
if (in_diff) {
printf("!!! sample %d, %d differences at %d / %d\n", index, sample_data1.GetDataSize()-diff_start, diff_start, sample_data1.GetDataSize());
}
}
/*----------------------------------------------------------------------
| DiffFragments
+---------------------------------------------------------------------*/
static void
DiffFragments(AP4_Movie& movie1, AP4_ByteStream* stream1, AP4_Movie& movie2, AP4_ByteStream* stream2)
{
stream1->Seek(0);
stream2->Seek(0);
AP4_LinearReader reader1(movie1, stream1);
AP4_LinearReader reader2(movie2, stream2);
AP4_List<AP4_Track>::Item* track_item1 = movie1.GetTracks().FirstItem();
AP4_List<AP4_Track>::Item* track_item2 = movie2.GetTracks().FirstItem();
while (track_item1 && track_item2) {
reader1.EnableTrack(track_item1->GetData()->GetId());
reader2.EnableTrack(track_item1->GetData()->GetId());
track_item1 = track_item1->GetNext();
track_item2 = track_item2->GetNext();
}
AP4_Sample sample1;
AP4_Sample sample2;
AP4_DataBuffer sample_data1;
AP4_DataBuffer sample_data2;
AP4_UI32 prev_track_id = 0;
for(unsigned int i=0; ; i++) {
AP4_UI32 track_id1 = 0;
AP4_UI32 track_id2 = 0;
AP4_Result result1 = reader1.ReadNextSample(sample1, sample_data1, track_id1);
AP4_Result result2 = reader2.ReadNextSample(sample2, sample_data2, track_id2);
if (AP4_SUCCEEDED(result1) && AP4_SUCCEEDED(result2)) {
if (track_id1 != track_id2) {
fprintf(stderr, "!!! sample %d, track ID 1 = %d, track ID 2 = %d\n", i, track_id1, track_id2);
return;
}
if (track_id1 != prev_track_id) {
printf("Track %d:\n", track_id1);
prev_track_id = track_id1;
}
DiffSamples(i, sample1, sample_data1, sample2, sample_data2);
} else {
printf("### processed %d samples\n", i+1);
break;
}
}
}
/*----------------------------------------------------------------------
| main
+---------------------------------------------------------------------*/
int
main(int argc, char** argv)
{
if (argc < 3) {
PrintUsageAndExit();
}
const char* filename1 = NULL;
const char* filename2 = NULL;
while (char* arg = *++argv) {
if (filename1 == NULL) {
filename1 = arg;
} else if (filename2 == NULL) {
filename2 = arg;
} else {
fprintf(stderr, "ERROR: unexpected argument '%s'\n", arg);
return 1;
}
}
if (filename1 == NULL || filename2 == NULL) {
fprintf(stderr, "ERROR: filename missing\n");
return 1;
}
AP4_ByteStream* input1 = NULL;
AP4_Result result = AP4_FileByteStream::Create(filename1,
AP4_FileByteStream::STREAM_MODE_READ,
input1);
if (AP4_FAILED(result)) {
fprintf(stderr, "ERROR: cannot open input file %s (%d)\n", filename1, result);
return 1;
}
AP4_ByteStream* input2 = NULL;
result = AP4_FileByteStream::Create(filename2,
AP4_FileByteStream::STREAM_MODE_READ,
input2);
if (AP4_FAILED(result)) {
fprintf(stderr, "ERROR: cannot open input file %s (%d)\n", filename2, result);
return 1;
}
AP4_File* file1 = new AP4_File(*input1, true);
AP4_File* file2 = new AP4_File(*input2, true);
AP4_Movie* movie1 = file1->GetMovie();
AP4_Movie* movie2 = file2->GetMovie();
if (movie1 && movie2) {
AP4_List<AP4_Track>& tracks1 = movie1->GetTracks();
AP4_List<AP4_Track>& tracks2 = movie1->GetTracks();
if (tracks1.ItemCount() != tracks2.ItemCount()) {
fprintf(stderr, "### file 1 has %d tracks, file 2 has %d tracks\n", tracks1.ItemCount(), tracks2.ItemCount());
} else {
for (unsigned int i=0; i<tracks1.ItemCount(); i++) {
AP4_Track* track1;
AP4_Track* track2;
tracks1.Get(i, track1);
tracks2.Get(i, track2);
printf("--- comparing track ID %d\n", track1->GetId());
}
}
if (movie1->HasFragments() != movie2->HasFragments()) {
fprintf(stderr, "### file 1 fragmented=%s, file2 fragmented=%s\n",
movie1->HasFragments() ? "true" : "false",
movie2->HasFragments() ? "true" : "false");
}
if (movie1->HasFragments() && movie2->HasFragments()) {
DiffFragments(*movie1, input1, *movie2, input2);
}
}
delete file1;
delete file2;
input1->Release();
input2->Release();
return 0;
}

View File

@@ -82,7 +82,7 @@ PrintUsageAndExit()
{
fprintf(stderr,
BANNER
"\n\nusage: mp4mux [options] --track [<type>:]<input>[#<params] [--track [<type>:]<input>[#<params] ...] <output>\n"
"\n\nusage: mp4mux [options] --track [<type>:]<input>[#<params>] [--track [<type>:]<input>[#<params>] ...] <output>\n"
"\n"
" <params>, when specified, are expressd as a comma-separated list of\n"
" one or more <name>=<value> parameters\n"

View File

@@ -236,16 +236,16 @@ public:
/**
* Feed some data to the parser and look for the next NAL Unit.
*
* @param data: Pointer to the memory buffer with the data to feed.
* @param data_size: Size in bytes of the buffer pointed to by the
* @param data Pointer to the memory buffer with the data to feed.
* @param data_size Size in bytes of the buffer pointed to by the
* data pointer.
* @param bytes_consumed: Number of bytes from the data buffer that were
* @param bytes_consumed Number of bytes from the data buffer that were
* consumed and stored by the parser.
* @param access_unit_info: Reference to a AccessUnitInfo structure that will
* @param access_unit_info Reference to a AccessUnitInfo structure that will
* contain information about any access unit found in the data. If no
* access unit was found, the nal_units field of this structure will be an
* empty array.
* @param eos: Boolean flag that indicates if this buffer is the last
* @param eos Boolean flag that indicates if this buffer is the last
* buffer in the stream/file (End Of Stream).
*
* @result: AP4_SUCCESS is the call succeeds, or an error code if it

View File

@@ -35,7 +35,7 @@
/*----------------------------------------------------------------------
| debugging
+---------------------------------------------------------------------*/
#define AP4_HEVC_PARSER_ENABLE_DEBUG 1
#define AP4_HEVC_PARSER_ENABLE_DEBUG 0
#if defined(AP4_HEVC_PARSER_ENABLE_DEBUG)
#define DBG_PRINTF_0(_x0) printf(_x0)
@@ -130,9 +130,9 @@ const char*
AP4_HevcNalParser::SliceTypeName(unsigned int slice_type)
{
switch (slice_type) {
case 0: return "B";
case 1: return "P";
case 2: return "I";
case AP4_HEVC_SLICE_TYPE_B: return "B";
case AP4_HEVC_SLICE_TYPE_P: return "P";
case AP4_HEVC_SLICE_TYPE_I: return "I";
default: return NULL;
}
}
@@ -190,6 +190,91 @@ AP4_HevcNalParser::AP4_HevcNalParser() :
{
}
/*----------------------------------------------------------------------
| scaling_list_data
+---------------------------------------------------------------------*/
static void
scaling_list_data(AP4_BitReader& bits)
{
for (unsigned int sizeId = 0; sizeId < 4; sizeId++) {
for (unsigned int matrixId = 0; matrixId < ((sizeId == 3)?2:6); matrixId++) {
unsigned int flag = bits.ReadBit(); // scaling_list_pred_mode_flag[ sizeId ][ matrixId ]
if (!flag) {
ReadGolomb(bits); // scaling_list_pred_matrix_id_delta[ sizeId ][ matrixId ]
} else {
// nextCoef = 8;
unsigned int coefNum = (1 << (4+(sizeId << 1)));
if (coefNum > 64) coefNum = 64;
if (sizeId > 1) {
ReadGolomb(bits); // scaling_list_dc_coef_minus8[ sizeId 2 ][ matrixId ]
// nextCoef = scaling_list_dc_coef_minus8[ sizeId 2 ][ matrixId ] + 8
}
for (unsigned i = 0; i < coefNum; i++) {
ReadGolomb(bits); // scaling_list_delta_coef
// nextCoef = ( nextCoef + scaling_list_delta_coef + 256 ) % 256
// ScalingList[ sizeId ][ matrixId ][ i ] = nextCoef
}
}
}
}
}
/*----------------------------------------------------------------------
| short_term_ref_pic_set
+---------------------------------------------------------------------*/
typedef struct {
unsigned int delta_poc_s0_minus1[16];
unsigned int delta_poc_s1_minus1[16];
unsigned int used_by_curr_pic_s0_flag[16];
unsigned int used_by_curr_pic_s1_flag[16];
} short_term_ref_pic_set;
static AP4_Result
parse_short_term_ref_pic_set(short_term_ref_pic_set* rps, unsigned int stRpsIdx, unsigned int num_short_term_ref_pic_sets, AP4_BitReader& bits) {
AP4_SetMemory(rps, 0, sizeof(*rps));
unsigned int inter_ref_pic_set_prediction_flag = 0;
if (stRpsIdx != 0) {
inter_ref_pic_set_prediction_flag = bits.ReadBit();
}
if (inter_ref_pic_set_prediction_flag) {
unsigned int delta_idx_minus1 = 0;
if (stRpsIdx == num_short_term_ref_pic_sets) {
delta_idx_minus1 = ReadGolomb(bits);
}
/* delta_rps_sign = */ bits.ReadBit();
/* abs_delta_rps_minus1 = */ ReadGolomb(bits);
if (delta_idx_minus1+1 > stRpsIdx) return AP4_ERROR_INVALID_FORMAT; // should not happen
//unsigned int RefRpsIdx = stRpsIdx - (delta_idx_minus1 + 1);
// TODO: finish parsing this
printf("### This bitstream uses features that are not yet supported. Please file a ticket.");
return AP4_ERROR_NOT_SUPPORTED;
// for (unsigned j=0; j<=NumDeltaPocs[RefRpsIdx]; j++) {
// unsigned int used_by_curr_pic_flag /*[j]*/ = bits.ReadBit();
// if (!used_by_curr_pic_flag /*[j]*/) {
// /* use_delta_flag[j] = */ bits.ReadBit();
// }
// }
// <TODO
} else {
unsigned int num_negative_pics = ReadGolomb(bits);
unsigned int num_positive_pics = ReadGolomb(bits);
if (num_negative_pics > 16 || num_positive_pics > 16) {
return AP4_ERROR_INVALID_FORMAT;
}
for (unsigned int i=0; i<num_negative_pics; i++) {
rps->delta_poc_s0_minus1[i] = ReadGolomb(bits);
rps->used_by_curr_pic_s0_flag[i] = bits.ReadBit();
}
for (unsigned i=0; i<num_positive_pics; i++) {
rps->delta_poc_s1_minus1[i] = ReadGolomb(bits);
rps->used_by_curr_pic_s1_flag[i] = bits.ReadBit();
}
}
return AP4_SUCCESS;
}
/*----------------------------------------------------------------------
| AP4_HevcSliceSegmentHeader::Parse
+---------------------------------------------------------------------*/
@@ -202,6 +287,10 @@ AP4_HevcSliceSegmentHeader::Parse(const AP4_UI08* data,
// initialize all members to 0
AP4_SetMemory(this, 0, sizeof(*this));
// some fields default to 1
pic_output_flag = 1;
// start the parser
AP4_DataBuffer unescaped(data, data_size);
AP4_NalParser::Unescape(unescaped);
AP4_BitReader bits(unescaped.GetData(), unescaped.GetDataSize());
@@ -242,39 +331,182 @@ AP4_HevcSliceSegmentHeader::Parse(const AP4_UI08* data,
}
unsigned int bits_needed = BitsNeeded(PicSizeInCtbsY);
slice_segment_address = bits.ReadBits(bits_needed);
if (bits_needed) {
slice_segment_address = bits.ReadBits(bits_needed);
}
}
if (!dependent_slice_segment_flag) {
bits.ReadBits(pps->num_extra_slice_header_bits);
if (pps->num_extra_slice_header_bits) {
bits.ReadBits(pps->num_extra_slice_header_bits); // slice_reserved_flag[...]
}
slice_type = ReadGolomb(bits);
if (slice_type != AP4_HEVC_SLICE_TYPE_B && slice_type != AP4_HEVC_SLICE_TYPE_P && slice_type != AP4_HEVC_SLICE_TYPE_I) {
return AP4_ERROR_INVALID_FORMAT;
}
if (pps->output_flag_present_flag) {
pic_output_flag = bits.ReadBit();
}
if (sps->separate_colour_plane_flag) {
colour_plane_id = bits.ReadBits(2);
}
unsigned int slice_sao_luma_flag = 0;
unsigned int slice_sao_chroma_flag = 0;
unsigned int slice_deblocking_filter_disabled_flag = 0;
unsigned int slice_temporal_mvp_enabled_flag = 0;
if (nal_unit_type != AP4_HEVC_NALU_TYPE_IDR_W_RADL && nal_unit_type != AP4_HEVC_NALU_TYPE_IDR_N_LP) {
slice_pic_order_cnt_lsb = bits.ReadBits(sps->log2_max_pic_order_cnt_lsb_minus4+4);
short_term_ref_pic_set_sps_flag = bits.ReadBit();
if (!short_term_ref_pic_set_sps_flag) {
// short_term_ref_pic_set(num_short_term_ref_pic_sets)
unsigned int stRpsIdx = sps->num_short_term_ref_pic_sets;
unsigned int inter_ref_pic_set_prediction_flag = 0;
if (stRpsIdx != 0) {
inter_ref_pic_set_prediction_flag = bits.ReadBit();
}
if (inter_ref_pic_set_prediction_flag) {
if (stRpsIdx == sps->num_short_term_ref_pic_sets) {
}
} else {
}
short_term_ref_pic_set rps;
AP4_Result result = parse_short_term_ref_pic_set(&rps, sps->num_short_term_ref_pic_sets, sps->num_short_term_ref_pic_sets, bits);
if (AP4_FAILED(result)) return result;
} else if (sps->num_short_term_ref_pic_sets > 1) {
short_term_ref_pic_set_idx = bits.ReadBits(BitsNeeded(sps->num_short_term_ref_pic_sets));
}
if (sps->long_term_ref_pics_present_flag) {
unsigned int num_long_term_sps = 0;
if (sps->num_long_term_ref_pics_sps > 0) {
num_long_term_sps = ReadGolomb(bits);
}
unsigned int num_long_term_pics = ReadGolomb(bits);
for (unsigned int i=0; i<num_long_term_sps + num_long_term_pics; i++) {
if (i < num_long_term_sps) {
if (sps->num_long_term_ref_pics_sps > 1) {
/* lt_idx_sps[i] = */ bits.ReadBits(BitsNeeded(sps->num_long_term_ref_pics_sps));
}
} else {
/* poc_lsb_lt[i] = */ bits.ReadBits(sps->log2_max_pic_order_cnt_lsb_minus4+4);
/* used_by_curr_pic_lt_flag[i] = */ bits.ReadBit();
}
unsigned int delta_poc_msb_present_flag /*[i]*/ = bits.ReadBit();
if (delta_poc_msb_present_flag /*[i]*/) {
/* delta_poc_msb_cycle_lt[i] = */ ReadGolomb(bits);
}
}
}
if (sps->sps_temporal_mvp_enabled_flag) {
slice_temporal_mvp_enabled_flag = bits.ReadBit();
}
}
if (sps->sample_adaptive_offset_enabled_flag) {
slice_sao_luma_flag = bits.ReadBit();
unsigned int ChromaArrayType = sps->separate_colour_plane_flag ? 0 : sps->chroma_format_idc;
if (ChromaArrayType) {
slice_sao_chroma_flag = bits.ReadBit();
}
}
if (slice_type == AP4_HEVC_SLICE_TYPE_P || slice_type == AP4_HEVC_SLICE_TYPE_B) {
unsigned int num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1;
unsigned int num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1;
unsigned int num_ref_idx_active_override_flag = bits.ReadBit();
if (num_ref_idx_active_override_flag) {
num_ref_idx_l0_active_minus1 = ReadGolomb(bits);
if (slice_type == AP4_HEVC_SLICE_TYPE_B) {
num_ref_idx_l1_active_minus1 = ReadGolomb(bits);
}
}
if (num_ref_idx_l0_active_minus1 > 14 || num_ref_idx_l1_active_minus1 > 14) {
return AP4_ERROR_INVALID_FORMAT;
}
// TODO: finish parsing this
//if (pps->lists_modification_present_flag && NumPicTotalCurr > 1) {
//ref_pic_lists_modification( )
//}
if (slice_type == AP4_HEVC_SLICE_TYPE_B) {
/* mvd_l1_zero_flag = */ bits.ReadBit();
}
if (pps->cabac_init_present_flag) {
/* cabac_init_flag = */ bits.ReadBit();
}
if (slice_temporal_mvp_enabled_flag) {
unsigned int collocated_from_l0_flag = 1;
if (slice_type == AP4_HEVC_SLICE_TYPE_B) {
collocated_from_l0_flag = bits.ReadBit();
}
if (( collocated_from_l0_flag && num_ref_idx_l0_active_minus1 > 0) ||
(!collocated_from_l0_flag && num_ref_idx_l1_active_minus1 > 0)) {
/* collocated_ref_idx = */ ReadGolomb(bits);
}
}
if ((pps->weighted_pred_flag && slice_type == AP4_HEVC_SLICE_TYPE_P) ||
(pps->weighted_bipred_flag && slice_type == AP4_HEVC_SLICE_TYPE_B)) {
// +++ pred_weight_table()
/* luma_log2_weight_denom = */ ReadGolomb(bits);
if (sps->chroma_format_idc != 0) {
/* delta_chroma_log2_weight_denom = */ /* SignedGolomb( */ ReadGolomb(bits) /*)*/;
}
unsigned int luma_weight_l0_flag[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
for (unsigned int i=0; i<=num_ref_idx_l0_active_minus1; i++) {
luma_weight_l0_flag[i] = bits.ReadBit();
}
unsigned int chroma_weight_l0_flag[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
if (sps->chroma_format_idc != 0) {
for (unsigned int i=0; i<=num_ref_idx_l0_active_minus1; i++) {
chroma_weight_l0_flag[i] = bits.ReadBit();
}
}
for (unsigned int i=0; i<=num_ref_idx_l0_active_minus1; i++) {
if (luma_weight_l0_flag[i]) {
/* delta_luma_weight_l0[i] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/;
/* luma_offset_l0[i] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/;
}
if (chroma_weight_l0_flag[i]) {
for (unsigned int j=0; j<2; j++) {
/* delta_chroma_weight_l0[i][j] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/;
/* delta_chroma_offset_l0[i][j] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/;
}
}
}
if (slice_type == AP4_HEVC_SLICE_TYPE_B) {
unsigned int luma_weight_l1_flag[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
for (unsigned int i=0; i<=num_ref_idx_l1_active_minus1; i++) {
luma_weight_l1_flag[i] = bits.ReadBit();
}
unsigned int chroma_weight_l1_flag[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
if (sps->chroma_format_idc != 0) {
for (unsigned int i=0; i<=num_ref_idx_l1_active_minus1; i++) {
chroma_weight_l1_flag[i] = bits.ReadBit();
}
}
for (unsigned int i=0; i<=num_ref_idx_l1_active_minus1; i++) {
if (luma_weight_l1_flag[i]) {
/* delta_luma_weight_l1[i] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/;
/* luma_offset_l1[i] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/;
}
if (chroma_weight_l1_flag[i]) {
for (unsigned int j=0; j<2; j++) {
/* delta_chroma_weight_l1[i][j] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/;
/* delta_chroma_offset_l1[i][j] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/;
}
}
}
}
// --- pred_weight_table()
}
/* five_minus_max_num_merge_cand = */ ReadGolomb(bits);
}
/* slice_qp_delta = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/;
if (pps->pps_slice_chroma_qp_offsets_present_flag) {
/* slice_cb_qp_offset = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/;
/* slice_cr_qp_offset = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/;
}
unsigned int deblocking_filter_override_flag = 0;
if (pps->deblocking_filter_override_enabled_flag) {
deblocking_filter_override_flag = bits.ReadBit();
}
if (deblocking_filter_override_flag) {
slice_deblocking_filter_disabled_flag = bits.ReadBit();
if (!slice_deblocking_filter_disabled_flag) {
/* slice_beta_offset_div2 = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/;
/* slice_tc_offset_div2 = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/;
}
}
if (pps->pps_loop_filter_across_slices_enabled_flag &&
(slice_sao_luma_flag || slice_sao_chroma_flag || !slice_deblocking_filter_disabled_flag)) {
/* slice_loop_filter_across_slices_enabled_flag = */ bits.ReadBit();
}
}
@@ -282,11 +514,11 @@ AP4_HevcSliceSegmentHeader::Parse(const AP4_UI08* data,
num_entry_point_offsets = ReadGolomb(bits);
if (num_entry_point_offsets > 0 ) {
offset_len_minus1 = ReadGolomb(bits);
if (offset_len_minus1 > 31) {
return AP4_ERROR_INVALID_FORMAT;
}
for (unsigned int i=0; i<num_entry_point_offsets; i++) {
// the value of num_entry_point_offsets shall be in the range of
// 0 to ( num_tile_columns_minus1 + 1 ) * PicHeightInCtbsY 1, inclusive.
unsigned int bits_needed = BitsNeeded((pps->num_tile_columns_minus1 + 1) * PicHeightInCtbsY - 1);
bits.ReadBits(bits_needed);
bits.ReadBits(offset_len_minus1+1);
}
}
}
@@ -300,6 +532,7 @@ AP4_HevcSliceSegmentHeader::Parse(const AP4_UI08* data,
/* compute the size */
size = bits.GetBitsRead();
DBG_PRINTF_1("*** slice segment header size=%d bits\n", size);
return AP4_SUCCESS;
}
@@ -391,7 +624,7 @@ AP4_HevcPictureParameterSet::AP4_HevcPictureParameterSet() :
entropy_coding_sync_enabled_flag(0),
num_tile_columns_minus1(0),
num_tile_rows_minus1(0),
uniform_spacing_flag(0),
uniform_spacing_flag(1),
loop_filter_across_tiles_enabled_flag(0),
pps_loop_filter_across_slices_enabled_flag(0),
deblocking_filter_control_present_flag(0),
@@ -406,35 +639,6 @@ AP4_HevcPictureParameterSet::AP4_HevcPictureParameterSet() :
{
}
/*----------------------------------------------------------------------
| scaling_list_data
+---------------------------------------------------------------------*/
static void
scaling_list_data(AP4_BitReader& bits)
{
for (unsigned int sizeId = 0; sizeId < 4; sizeId++) {
for (unsigned int matrixId = 0; matrixId < ((sizeId == 3)?2:6); matrixId++) {
unsigned int flag = bits.ReadBit(); // scaling_list_pred_mode_flag[ sizeId ][ matrixId ]
if (!flag) {
ReadGolomb(bits); // scaling_list_pred_matrix_id_delta[ sizeId ][ matrixId ]
} else {
// nextCoef = 8;
unsigned int coefNum = (1 << (4+(sizeId << 1)));
if (coefNum > 64) coefNum = 64;
if (sizeId > 1) {
ReadGolomb(bits); // scaling_list_dc_coef_minus8[ sizeId 2 ][ matrixId ]
// nextCoef = scaling_list_dc_coef_minus8[ sizeId 2 ][ matrixId ] + 8
}
for (unsigned i = 0; i < coefNum; i++) {
ReadGolomb(bits); // scaling_list_delta_coef
// nextCoef = ( nextCoef + scaling_list_delta_coef + 256 ) % 256
// ScalingList[ sizeId ][ matrixId ][ i ] = nextCoef
}
}
}
}
}
/*----------------------------------------------------------------------
| AP4_HevcPictureParameterSet::Parse
+---------------------------------------------------------------------*/
@@ -551,7 +755,11 @@ AP4_HevcSequenceParameterSet::AP4_HevcSequenceParameterSet() :
log2_min_pcm_luma_coding_block_size_minus3(0),
log2_diff_max_min_pcm_luma_coding_block_size(0),
pcm_loop_filter_disabled_flag(0),
num_short_term_ref_pic_sets(0)
num_short_term_ref_pic_sets(0),
long_term_ref_pics_present_flag(0),
num_long_term_ref_pics_sps(0),
sps_temporal_mvp_enabled_flag(0),
strong_intra_smoothing_enabled_flag(0)
{
AP4_SetMemory(&profile_tier_level, 0, sizeof(profile_tier_level));
for (unsigned int i=0; i<8; i++) {
@@ -623,7 +831,43 @@ AP4_HevcSequenceParameterSet::Parse(const unsigned char* data, unsigned int data
log2_diff_max_min_transform_block_size = ReadGolomb(bits);
max_transform_hierarchy_depth_inter = ReadGolomb(bits);
max_transform_hierarchy_depth_intra = ReadGolomb(bits);
scaling_list_enabled_flag = bits.ReadBit();
if (scaling_list_enabled_flag) {
sps_scaling_list_data_present_flag = bits.ReadBit();
if (sps_scaling_list_data_present_flag) {
scaling_list_data(bits);
}
}
amp_enabled_flag = bits.ReadBit();
sample_adaptive_offset_enabled_flag = bits.ReadBit();
pcm_enabled_flag = bits.ReadBit();
if (pcm_enabled_flag) {
pcm_sample_bit_depth_luma_minus1 = bits.ReadBits(4);
pcm_sample_bit_depth_chroma_minus1 = bits.ReadBits(4);
log2_min_pcm_luma_coding_block_size_minus3 = ReadGolomb(bits);
log2_diff_max_min_pcm_luma_coding_block_size = ReadGolomb(bits);
pcm_loop_filter_disabled_flag = bits.ReadBit();
}
num_short_term_ref_pic_sets = ReadGolomb(bits);
if (num_short_term_ref_pic_sets > 64) {
return AP4_ERROR_INVALID_FORMAT;
}
for (unsigned int i=0; i<num_short_term_ref_pic_sets; i++) {
short_term_ref_pic_set rps;
AP4_Result result = parse_short_term_ref_pic_set(&rps, i, num_short_term_ref_pic_sets, bits);
if (AP4_FAILED(result)) return result;
}
long_term_ref_pics_present_flag = bits.ReadBit();
if (long_term_ref_pics_present_flag) {
num_long_term_ref_pics_sps = ReadGolomb(bits);
for (unsigned int i=0; i<num_long_term_ref_pics_sps; i++) {
/* lt_ref_pic_poc_lsb_sps[i] = */ bits.ReadBits(log2_max_pic_order_cnt_lsb_minus4 + 4);
/* used_by_curr_pic_lt_sps_flag[i] = */ bits.ReadBit();
}
}
sps_temporal_mvp_enabled_flag = bits.ReadBit();
strong_intra_smoothing_enabled_flag = bits.ReadBit();
return AP4_SUCCESS;
}

View File

@@ -102,6 +102,10 @@ const unsigned int AP4_HEVC_ACCESS_UNIT_FLAG_IS_RADL = 0x08;
const unsigned int AP4_HEVC_ACCESS_UNIT_FLAG_IS_RASL = 0x10;
const unsigned int AP4_HEVC_ACCESS_UNIT_FLAG_IS_SUBLAYER_NON_REF = 0x20;
const unsigned int AP4_HEVC_SLICE_TYPE_B = 0;
const unsigned int AP4_HEVC_SLICE_TYPE_P = 1;
const unsigned int AP4_HEVC_SLICE_TYPE_I = 2;
/*----------------------------------------------------------------------
| class references
+---------------------------------------------------------------------*/
@@ -243,6 +247,10 @@ struct AP4_HevcSequenceParameterSet {
unsigned int log2_diff_max_min_pcm_luma_coding_block_size;
unsigned int pcm_loop_filter_disabled_flag;
unsigned int num_short_term_ref_pic_sets;
unsigned int long_term_ref_pics_present_flag;
unsigned int num_long_term_ref_pics_sps;
unsigned int sps_temporal_mvp_enabled_flag;
unsigned int strong_intra_smoothing_enabled_flag;
};
/*----------------------------------------------------------------------
@@ -336,16 +344,16 @@ public:
/**
* Feed some data to the parser and look for the next NAL Unit.
*
* @param data: Pointer to the memory buffer with the data to feed.
* @param data_size: Size in bytes of the buffer pointed to by the
* @param data Pointer to the memory buffer with the data to feed.
* @param data_size Size in bytes of the buffer pointed to by the
* data pointer.
* @param bytes_consumed: Number of bytes from the data buffer that were
* @param bytes_consumed Number of bytes from the data buffer that were
* consumed and stored by the parser.
* @param access_unit_info: Reference to a AccessUnitInfo structure that will
* @param access_unit_info Reference to a AccessUnitInfo structure that will
* contain information about any access unit found in the data. If no
* access unit was found, the nal_units field of this structure will be an
* empty array.
* @param eos: Boolean flag that indicates if this buffer is the last
* @param eos Boolean flag that indicates if this buffer is the last
* buffer in the stream/file (End Of Stream).
*
* @result: AP4_SUCCESS is the call succeeds, or an error code if it

View File

@@ -49,15 +49,15 @@ public:
/**
* Feed some data to the parser and look for the next NAL Unit.
*
* @param data: Pointer to the memory buffer with the data to feed.
* @param data_size: Size in bytes of the buffer pointed to by the
* @param data Pointer to the memory buffer with the data to feed.
* @param data_size Size in bytes of the buffer pointed to by the
* data pointer.
* @param bytes_consumed: Number of bytes from the data buffer that were
* @param bytes_consumed Number of bytes from the data buffer that were
* consumed and stored by the parser.
* @param nalu: Reference to a pointer to a buffer object that contains
* @param nalu Reference to a pointer to a buffer object that contains
* a NAL unit found in the previously fed data, or a NULL pointer if no
* NAL unit can be found so far.
* @param eos: Boolean flag that indicates if this buffer is the last
* @param eos Boolean flag that indicates if this buffer is the last
* buffer in the stream/file (End Of Stream).
*
* @result: AP4_SUCCESS is the call succeeds, or an error code if it

View File

@@ -412,7 +412,11 @@ AP4_CencCbcsSubSampleMapper::GetSubSampleMap(AP4_DataBuffer& sample_data,
}
// leave the slice header in the clear, including the NAL type
unsigned int cleartext_size = m_NaluLengthSize+2+(slice_header.size+7)/8;
//unsigned int cleartext_size = m_NaluLengthSize+2+(slice_header.size+7)/8;
// HACK: add one byte when the slice header is a multiple of 8 bits, to match what Apple is doing
unsigned int header_size = 1+(slice_header.size/8);
unsigned int cleartext_size = m_NaluLengthSize+2+header_size;
//
unsigned int encrypted_size = nalu_size-cleartext_size;
bytes_of_cleartext_data.Append(cleartext_size);

View File

@@ -93,7 +93,7 @@ public:
/**
* Constructs an AP4_File from a stream
* @param stream the stream containing the data of the file
* @param factory the atom factory that will be used to parse the stream
* @param atom_factory the atom factory that will be used to parse the stream
* @param moov_only indicates whether parsing of the atoms should stop
* when the moov atom is found or if all atoms should be parsed until the
* end of the file.

View File

@@ -57,7 +57,7 @@ public:
// constructor
/**
* @param: ohdr ohdr atom passed with transfer of ownership semantics
* @param ohdr ohdr atom passed with transfer of ownership semantics
*/
AP4_OdheAtom(const char* content_type, AP4_OhdrAtom* ohdr);

View File

@@ -440,6 +440,7 @@ AP4_BitReader::ReadCache() const
AP4_UI32
AP4_BitReader::ReadBits(unsigned int n)
{
if (n == 0) return 0;
AP4_BitReader::BitsWord result;
if (m_BitsCached >= n) {
/* we have enough bits in the cache to satisfy the request */