Implement write function for cenc and es_descriptor.
And MP4 code clean ups due to mp4 box changes. Change-Id: I712b2dceb5038bfefa14097fe2fb2ab1fb913cb5
This commit is contained in:
parent
dccb069ffc
commit
01646837e1
|
@ -17,8 +17,6 @@ DecryptConfig::DecryptConfig(const std::string& key_id,
|
|||
data_offset_(data_offset),
|
||||
subsamples_(subsamples) {
|
||||
CHECK_GT(key_id.size(), 0u);
|
||||
CHECK(iv.size() == static_cast<size_t>(DecryptConfig::kDecryptionKeySize) ||
|
||||
iv.empty());
|
||||
CHECK_GE(data_offset, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace media {
|
|||
// result, and then copying each byte from the decrypted block over the
|
||||
// position of the corresponding encrypted byte.
|
||||
struct SubsampleEntry {
|
||||
uint32 clear_bytes;
|
||||
uint16 clear_bytes;
|
||||
uint32 cypher_bytes;
|
||||
};
|
||||
|
||||
|
@ -31,12 +31,10 @@ struct SubsampleEntry {
|
|||
class DecryptConfig {
|
||||
public:
|
||||
// Keys are always 128 bits.
|
||||
static const int kDecryptionKeySize = 16;
|
||||
static const size_t kDecryptionKeySize = 16;
|
||||
|
||||
// |key_id| is the ID that references the decryption key for this sample.
|
||||
// |iv| is the initialization vector defined by the encrypted format.
|
||||
// Currently |iv| must be 16 bytes as defined by WebM and ISO. Or must be
|
||||
// empty which signals an unencrypted frame.
|
||||
// |data_offset| is the amount of data that should be discarded from the
|
||||
// head of the sample buffer before applying subsample information. A
|
||||
// decrypted buffer will be shorter than an encrypted buffer by this amount.
|
||||
|
|
|
@ -37,8 +37,6 @@ AAC::~AAC() {
|
|||
}
|
||||
|
||||
bool AAC::Parse(const std::vector<uint8>& data) {
|
||||
codec_specific_data_ = data;
|
||||
|
||||
if (data.empty())
|
||||
return false;
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ class AAC {
|
|||
// The function will parse the data and get the ElementaryStreamDescriptor,
|
||||
// then it will parse the ElementaryStreamDescriptor to get audio stream
|
||||
// configurations.
|
||||
// |data| is always copied to |codec_specific_data_|.
|
||||
bool Parse(const std::vector<uint8>& data);
|
||||
|
||||
// Gets the output sample rate for the AAC stream.
|
||||
|
@ -61,11 +60,6 @@ class AAC {
|
|||
return num_channels_;
|
||||
}
|
||||
|
||||
// Returns the codec specific data.
|
||||
std::vector<uint8> codec_specific_data() const {
|
||||
return codec_specific_data_;
|
||||
}
|
||||
|
||||
// Size in bytes of the ADTS header added by ConvertEsdsToADTS().
|
||||
static const size_t kADTSHeaderSize = 7;
|
||||
|
||||
|
@ -82,8 +76,6 @@ class AAC {
|
|||
// Is Parametric Stereo on?
|
||||
bool ps_present_;
|
||||
|
||||
std::vector<uint8> codec_specific_data_;
|
||||
|
||||
// The following variables store audio configuration information.
|
||||
// They are based on the AAC specific configuration but can be overridden
|
||||
// by extensions in elementary stream descriptor.
|
||||
|
|
|
@ -6,46 +6,82 @@
|
|||
|
||||
#include <cstring>
|
||||
|
||||
#include "media/mp4/box_reader.h"
|
||||
#include "media/base/buffer_reader.h"
|
||||
#include "media/base/buffer_writer.h"
|
||||
#include "media/mp4/rcheck.h"
|
||||
|
||||
namespace {
|
||||
// According to ISO/IEC FDIS 23001-7: CENC spec, IV should be either
|
||||
// 64-bit (8-byte) or 128-bit (16-byte).
|
||||
bool IsIvSizeValid(size_t iv_size) { return iv_size == 8 || iv_size == 16; }
|
||||
|
||||
// 16-bit |clear_bytes| and 32-bit |cypher_bytes|.
|
||||
const size_t kSubsampleEntrySize = sizeof(uint16) + sizeof(uint32);
|
||||
} // namespace
|
||||
|
||||
namespace media {
|
||||
namespace mp4 {
|
||||
|
||||
FrameCENCInfo::FrameCENCInfo() {}
|
||||
FrameCENCInfo::FrameCENCInfo(const std::vector<uint8>& iv) : iv_(iv) {}
|
||||
FrameCENCInfo::~FrameCENCInfo() {}
|
||||
|
||||
bool FrameCENCInfo::Parse(int iv_size, BufferReader* reader) {
|
||||
const int kEntrySize = 6;
|
||||
// Mandated by CENC spec
|
||||
RCHECK(iv_size == 8 || iv_size == 16);
|
||||
bool FrameCENCInfo::Parse(uint8 iv_size, BufferReader* reader) {
|
||||
DCHECK(reader);
|
||||
// Mandated by CENC spec.
|
||||
RCHECK(IsIvSizeValid(iv_size));
|
||||
|
||||
memset(iv, 0, sizeof(iv));
|
||||
for (int i = 0; i < iv_size; i++)
|
||||
RCHECK(reader->Read1(&iv[i]));
|
||||
iv_.resize(iv_size);
|
||||
RCHECK(reader->ReadToVector(&iv_, iv_size));
|
||||
|
||||
if (!reader->HasBytes(1)) return true;
|
||||
if (!reader->HasBytes(1))
|
||||
return true;
|
||||
|
||||
uint16 subsample_count;
|
||||
RCHECK(reader->Read2(&subsample_count) &&
|
||||
reader->HasBytes(subsample_count * kEntrySize));
|
||||
reader->HasBytes(subsample_count * kSubsampleEntrySize));
|
||||
|
||||
subsamples.resize(subsample_count);
|
||||
for (int i = 0; i < subsample_count; i++) {
|
||||
subsamples_.resize(subsample_count);
|
||||
for (uint16 i = 0; i < subsample_count; ++i) {
|
||||
uint16 clear_bytes;
|
||||
uint32 cypher_bytes;
|
||||
RCHECK(reader->Read2(&clear_bytes) &&
|
||||
reader->Read4(&cypher_bytes));
|
||||
subsamples[i].clear_bytes = clear_bytes;
|
||||
subsamples[i].cypher_bytes = cypher_bytes;
|
||||
subsamples_[i].clear_bytes = clear_bytes;
|
||||
subsamples_[i].cypher_bytes = cypher_bytes;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FrameCENCInfo::Write(BufferWriter* writer) const {
|
||||
DCHECK(writer);
|
||||
DCHECK(IsIvSizeValid(iv_.size()));
|
||||
writer->AppendVector(iv_);
|
||||
|
||||
uint16 subsample_count = subsamples_.size();
|
||||
if (subsample_count == 0)
|
||||
return;
|
||||
writer->AppendInt(subsample_count);
|
||||
|
||||
for (uint16 i = 0; i < subsample_count; ++i) {
|
||||
writer->AppendInt(subsamples_[i].clear_bytes);
|
||||
writer->AppendInt(subsamples_[i].cypher_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
size_t FrameCENCInfo::ComputeSize() const {
|
||||
uint16 subsample_count = subsamples_.size();
|
||||
if (subsample_count == 0)
|
||||
return iv_.size();
|
||||
|
||||
return iv_.size() + sizeof(subsample_count) +
|
||||
subsample_count * kSubsampleEntrySize;
|
||||
}
|
||||
|
||||
size_t FrameCENCInfo::GetTotalSizeOfSubsamples() const {
|
||||
size_t size = 0;
|
||||
for (size_t i = 0; i < subsamples.size(); i++) {
|
||||
size += subsamples[i].clear_bytes + subsamples[i].cypher_bytes;
|
||||
for (size_t i = 0; i < subsamples_.size(); ++i) {
|
||||
size += subsamples_[i].clear_bytes + subsamples_[i].cypher_bytes;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
|
|
@ -11,20 +11,37 @@
|
|||
#include "media/base/decrypt_config.h"
|
||||
|
||||
namespace media {
|
||||
namespace mp4 {
|
||||
|
||||
class BufferReader;
|
||||
class BufferWriter;
|
||||
|
||||
struct FrameCENCInfo {
|
||||
uint8 iv[16];
|
||||
std::vector<SubsampleEntry> subsamples;
|
||||
namespace mp4 {
|
||||
|
||||
class FrameCENCInfo {
|
||||
public:
|
||||
FrameCENCInfo();
|
||||
explicit FrameCENCInfo(const std::vector<uint8>& iv);
|
||||
~FrameCENCInfo();
|
||||
bool Parse(int iv_size, BufferReader* r);
|
||||
size_t GetTotalSizeOfSubsamples() const;
|
||||
};
|
||||
|
||||
bool Parse(uint8 iv_size, BufferReader* reader);
|
||||
void Write(BufferWriter* writer) const;
|
||||
size_t ComputeSize() const;
|
||||
size_t GetTotalSizeOfSubsamples() const;
|
||||
|
||||
void AddSubsample(const SubsampleEntry& subsample) {
|
||||
subsamples_.push_back(subsample);
|
||||
}
|
||||
|
||||
const std::vector<uint8>& iv() const { return iv_; }
|
||||
const std::vector<SubsampleEntry>& subsamples() const { return subsamples_; }
|
||||
|
||||
private:
|
||||
std::vector<uint8> iv_;
|
||||
std::vector<SubsampleEntry> subsamples_;
|
||||
|
||||
// Not using DISALLOW_COPY_AND_ASSIGN here intentionally to allow the compiler
|
||||
// generated copy constructor and assignment operator.
|
||||
};
|
||||
|
||||
} // namespace mp4
|
||||
} // namespace media
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "media/mp4/chunk_info_iterator.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
|
@ -18,8 +19,8 @@ namespace media {
|
|||
namespace mp4 {
|
||||
|
||||
const uint32 kNumChunks = 100;
|
||||
const ChunkInfo kChunkInfos[] =
|
||||
{{1, 8, 1}, {9, 5, 1}, {25, 7, 2}, {48, 63, 2}, {80, 2, 1}};
|
||||
const ChunkInfo kChunkInfos[] = {
|
||||
{1, 8, 1}, {9, 5, 1}, {25, 7, 2}, {48, 63, 2}, {80, 2, 1}};
|
||||
|
||||
class ChunkInfoIteratorTest : public testing::Test {
|
||||
public:
|
||||
|
@ -33,9 +34,8 @@ class ChunkInfoIteratorTest : public testing::Test {
|
|||
uint32 next_first_chunk =
|
||||
(i == length - 1) ? kNumChunks + 1 : kChunkInfos[i + 1].first_chunk;
|
||||
for (; chunk_index < next_first_chunk; ++chunk_index) {
|
||||
ChunkProperty chunk = {kChunkInfos[i].samples_per_chunk, kChunkInfos[i].sample_description_index};
|
||||
//chunk.samples_per_chunk = kChunkInfos[i].samples_per_chunk;
|
||||
//chunk.sample_description_index = kChunkInfos[i].sample_description_index;
|
||||
ChunkProperty chunk = {kChunkInfos[i].samples_per_chunk,
|
||||
kChunkInfos[i].sample_description_index};
|
||||
chunk_info_table_.push_back(chunk);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,36 @@
|
|||
#include "media/mp4/es_descriptor.h"
|
||||
|
||||
#include "media/base/bit_reader.h"
|
||||
#include "media/base/buffer_writer.h"
|
||||
#include "media/mp4/rcheck.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// ISO/IEC 14496-1:2004 Section 7.2.6.6 Table 6: StreamType values.
|
||||
enum StreamType {
|
||||
kForbiddenStreamType = 0x00,
|
||||
kObjectDescriptorStreamType = 0x01,
|
||||
kClockReferenceStreamType = 0x02,
|
||||
kSceneDescriptionStreamType = 0x03,
|
||||
kVisualStreamType = 0x04,
|
||||
kAudioStreamType = 0x05,
|
||||
kMPEG7StreamType = 0x06,
|
||||
kIPMPStreamType = 0x07,
|
||||
kObjectContentInfoStreamType = 0x08,
|
||||
kMPEGJStreamType = 0x09,
|
||||
kInteractionStream = 0x0A,
|
||||
kIPMPToolStreamType = 0x0B,
|
||||
};
|
||||
|
||||
// ISO/IEC 14496-1:2004 Section 7.3.2.3 Table 12: ISO SL Config Descriptor.
|
||||
enum SLPredefinedTags {
|
||||
kSLPredefinedNull = 0x01,
|
||||
kSLPredefinedMP4 = 0x02,
|
||||
};
|
||||
|
||||
// The elementary stream size is specific by up to 4 bytes.
|
||||
// The MSB of a byte indicates if there are more bytes for the size.
|
||||
static bool ReadESSize(media::BitReader* reader, uint32* size) {
|
||||
bool ReadESSize(media::BitReader* reader, uint32* size) {
|
||||
uint8 msb;
|
||||
uint8 byte;
|
||||
|
||||
|
@ -27,18 +52,18 @@ static bool ReadESSize(media::BitReader* reader, uint32* size) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Descryptor Header Size: 1 byte tag and 1 byte size (we don't support
|
||||
// multi-bytes size for now).
|
||||
const size_t kHeaderSize = 2;
|
||||
const size_t kMaxDecoderSpecificInfoSize = 64;
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace media {
|
||||
|
||||
namespace mp4 {
|
||||
|
||||
// static
|
||||
bool ESDescriptor::IsAAC(ObjectType object_type) {
|
||||
return object_type == kISO_14496_3 || object_type == kISO_13818_7_AAC_LC;
|
||||
}
|
||||
|
||||
ESDescriptor::ESDescriptor()
|
||||
: object_type_(kForbidden) {
|
||||
}
|
||||
ESDescriptor::ESDescriptor() : esid_(0), object_type_(kForbidden) {}
|
||||
|
||||
ESDescriptor::~ESDescriptor() {}
|
||||
|
||||
|
@ -55,7 +80,7 @@ bool ESDescriptor::Parse(const std::vector<uint8>& data) {
|
|||
RCHECK(tag == kESDescrTag);
|
||||
RCHECK(ReadESSize(&reader, &size));
|
||||
|
||||
RCHECK(reader.ReadBits(16, &dummy)); // ES_ID
|
||||
RCHECK(reader.ReadBits(16, &esid_)); // ES_ID
|
||||
RCHECK(reader.ReadBits(1, &stream_dependency_flag));
|
||||
RCHECK(reader.ReadBits(1, &url_flag));
|
||||
RCHECK(!url_flag); // We don't support url flag
|
||||
|
@ -72,14 +97,6 @@ bool ESDescriptor::Parse(const std::vector<uint8>& data) {
|
|||
return true;
|
||||
}
|
||||
|
||||
ObjectType ESDescriptor::object_type() const {
|
||||
return object_type_;
|
||||
}
|
||||
|
||||
const std::vector<uint8>& ESDescriptor::decoder_specific_info() const {
|
||||
return decoder_specific_info_;
|
||||
}
|
||||
|
||||
bool ESDescriptor::ParseDecoderConfigDescriptor(BitReader* reader) {
|
||||
uint8 tag;
|
||||
uint32 size;
|
||||
|
@ -98,6 +115,7 @@ bool ESDescriptor::ParseDecoderConfigDescriptor(BitReader* reader) {
|
|||
}
|
||||
|
||||
bool ESDescriptor::ParseDecoderSpecificInfo(BitReader* reader) {
|
||||
DCHECK(reader);
|
||||
uint8 tag;
|
||||
uint32 size;
|
||||
|
||||
|
@ -112,6 +130,65 @@ bool ESDescriptor::ParseDecoderSpecificInfo(BitReader* reader) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void ESDescriptor::Write(BufferWriter* writer) const {
|
||||
// TODO(kqyang): Consider writing Descriptor classes.
|
||||
// ElementaryStreamDescriptor, DecoderConfigDescriptor, SLConfigDescriptor,
|
||||
// DecoderSpecificInfoDescriptor.
|
||||
DCHECK(writer);
|
||||
CHECK_LT(decoder_specific_info_.size(), kMaxDecoderSpecificInfoSize);
|
||||
|
||||
const std::vector<uint8> kEmptyDecodingBufferSize(3, 0);
|
||||
const uint32 kUnknownBitrate = 0;
|
||||
const uint8 kNoEsFlags = 0;
|
||||
|
||||
const uint8 decoder_specific_info_size = decoder_specific_info_.size();
|
||||
|
||||
// 6 bit stream type. The last bit is reserved with 1.
|
||||
const uint8 stream_type = (kAudioStreamType << 2) | 1;
|
||||
const uint8 decoder_config_size = decoder_specific_info_size + kHeaderSize +
|
||||
sizeof(uint8) + // object_type_.
|
||||
sizeof(stream_type) +
|
||||
kEmptyDecodingBufferSize.size() +
|
||||
sizeof(kUnknownBitrate) * 2;
|
||||
|
||||
const uint8 sl_config_size = sizeof(uint8); // predefined.
|
||||
const uint8 es_size = decoder_config_size + kHeaderSize + sl_config_size +
|
||||
kHeaderSize + sizeof(esid_) + sizeof(kNoEsFlags);
|
||||
|
||||
writer->AppendInt(static_cast<uint8>(kESDescrTag));
|
||||
writer->AppendInt(es_size);
|
||||
writer->AppendInt(esid_);
|
||||
writer->AppendInt(kNoEsFlags);
|
||||
|
||||
writer->AppendInt(static_cast<uint8>(kDecoderConfigDescrTag));
|
||||
writer->AppendInt(decoder_config_size);
|
||||
writer->AppendInt(static_cast<uint8>(object_type_));
|
||||
writer->AppendInt(stream_type);
|
||||
writer->AppendVector(kEmptyDecodingBufferSize);
|
||||
writer->AppendInt(kUnknownBitrate); // max_bitrate.
|
||||
writer->AppendInt(kUnknownBitrate); // avg_bitrate.
|
||||
|
||||
writer->AppendInt(static_cast<uint8>(kDecoderSpecificInfoTag));
|
||||
writer->AppendInt(decoder_specific_info_size);
|
||||
writer->AppendVector(decoder_specific_info_);
|
||||
|
||||
writer->AppendInt(static_cast<uint8>(kSLConfigTag));
|
||||
writer->AppendInt(sl_config_size);
|
||||
writer->AppendInt(static_cast<uint8>(kSLPredefinedMP4));
|
||||
}
|
||||
|
||||
size_t ESDescriptor::ComputeSize() const {
|
||||
// A bit magical. Refer to ESDescriptor::Write for details.
|
||||
const uint8 decoder_specific_info_size = decoder_specific_info_.size();
|
||||
const uint8 decoder_config_size = decoder_specific_info_size + kHeaderSize +
|
||||
sizeof(uint8) * 5 + sizeof(uint32) * 2;
|
||||
const uint8 sl_config_size = sizeof(uint8);
|
||||
const uint8 es_size = decoder_config_size + kHeaderSize +
|
||||
sl_config_size + kHeaderSize +
|
||||
sizeof(esid_) + sizeof(uint8);
|
||||
return es_size + kHeaderSize;
|
||||
}
|
||||
|
||||
} // namespace mp4
|
||||
|
||||
} // namespace media
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
namespace media {
|
||||
|
||||
class BitReader;
|
||||
class BufferWriter;
|
||||
|
||||
namespace mp4 {
|
||||
|
||||
|
@ -29,27 +30,44 @@ enum ObjectType {
|
|||
// Please refer to ISO 14496 Part 1 7.2.6.5 for more details.
|
||||
class ESDescriptor {
|
||||
public:
|
||||
// Utility function to check if the given object type is AAC.
|
||||
static bool IsAAC(ObjectType object_type);
|
||||
|
||||
ESDescriptor();
|
||||
~ESDescriptor();
|
||||
|
||||
bool Parse(const std::vector<uint8>& data);
|
||||
void Write(BufferWriter* writer) const;
|
||||
size_t ComputeSize() const;
|
||||
|
||||
ObjectType object_type() const;
|
||||
const std::vector<uint8>& decoder_specific_info() const;
|
||||
uint16 esid() const { return esid_; }
|
||||
void set_esid(uint16 esid) { esid_ = esid; }
|
||||
|
||||
ObjectType object_type() const { return object_type_; }
|
||||
void set_object_type(ObjectType object_type) { object_type_ = object_type; }
|
||||
|
||||
const std::vector<uint8>& decoder_specific_info() const {
|
||||
return decoder_specific_info_;
|
||||
}
|
||||
void set_decoder_specific_info(
|
||||
const std::vector<uint8>& decoder_specific_info) {
|
||||
decoder_specific_info_ = decoder_specific_info;
|
||||
}
|
||||
|
||||
// Check if the stream is AAC.
|
||||
bool IsAAC() const {
|
||||
return object_type_ == kISO_14496_3 || object_type_ == kISO_13818_7_AAC_LC;
|
||||
}
|
||||
|
||||
private:
|
||||
enum Tag {
|
||||
kESDescrTag = 0x03,
|
||||
kDecoderConfigDescrTag = 0x04,
|
||||
kDecoderSpecificInfoTag = 0x05
|
||||
kDecoderSpecificInfoTag = 0x05,
|
||||
kSLConfigTag = 0x06,
|
||||
};
|
||||
|
||||
bool ParseDecoderConfigDescriptor(BitReader* reader);
|
||||
bool ParseDecoderSpecificInfo(BitReader* reader);
|
||||
|
||||
uint16 esid_; // Elementary Stream ID.
|
||||
ObjectType object_type_;
|
||||
std::vector<uint8> decoder_specific_info_;
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#define RCHECK(x) \
|
||||
do { \
|
||||
if (!(x)) { \
|
||||
DLOG(ERROR) << "Failure while parsing MP4: " << #x; \
|
||||
LOG(ERROR) << "Failure while processing MP4: " << #x; \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include "media/base/buffer_reader.h"
|
||||
#include "media/mp4/chunk_info_iterator.h"
|
||||
#include "media/mp4/composition_offset_iterator.h"
|
||||
#include "media/mp4/decoding_time_iterator.h"
|
||||
|
@ -90,12 +91,12 @@ static void PopulateSampleInfo(const TrackExtends& trex,
|
|||
uint32 flags;
|
||||
if (i < trun.sample_flags.size()) {
|
||||
flags = trun.sample_flags[i];
|
||||
} else if (tfhd.flags & kDefaultSampleFlagsPresentMask) {
|
||||
} else if (tfhd.flags & TrackFragmentHeader::kDefaultSampleFlagsPresentMask) {
|
||||
flags = tfhd.default_sample_flags;
|
||||
} else {
|
||||
flags = trex.default_sample_flags;
|
||||
}
|
||||
sample_info->is_keyframe = !(flags & kNonKeySampleMask);
|
||||
sample_info->is_keyframe = !(flags & TrackFragmentHeader::kNonKeySampleMask);
|
||||
}
|
||||
|
||||
// In well-structured encrypted media, each track run will be immediately
|
||||
|
@ -396,6 +397,7 @@ bool TrackRunIterator::AuxInfoNeedsToBeCached() {
|
|||
return is_encrypted() && aux_info_size() > 0 && cenc_info_.size() == 0;
|
||||
}
|
||||
|
||||
// TODO(kqyang): Revisit later. We might not need to cache cenc info.
|
||||
// This implementation currently only caches CENC auxiliary info.
|
||||
bool TrackRunIterator::CacheAuxInfo(const uint8* buf, int buf_size) {
|
||||
RCHECK(AuxInfoNeedsToBeCached() && buf_size >= aux_info_size());
|
||||
|
@ -525,8 +527,9 @@ scoped_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
|
|||
const FrameCENCInfo& cenc_info = cenc_info_[sample_idx];
|
||||
DCHECK(is_encrypted() && !AuxInfoNeedsToBeCached());
|
||||
|
||||
if (!cenc_info.subsamples.empty() && (cenc_info.GetTotalSizeOfSubsamples() !=
|
||||
static_cast<size_t>(sample_size()))) {
|
||||
const size_t total_size_of_subsamples = cenc_info.GetTotalSizeOfSubsamples();
|
||||
if (total_size_of_subsamples != 0 &&
|
||||
total_size_of_subsamples != static_cast<size_t>(sample_size())) {
|
||||
LOG(ERROR) << "Incorrect CENC subsample size.";
|
||||
return scoped_ptr<DecryptConfig>();
|
||||
}
|
||||
|
@ -534,9 +537,9 @@ scoped_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
|
|||
const std::vector<uint8>& kid = track_encryption().default_kid;
|
||||
return scoped_ptr<DecryptConfig>(new DecryptConfig(
|
||||
std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()),
|
||||
std::string(cenc_info.iv.begin(), cenc_info.iv.end()),
|
||||
std::string(cenc_info.iv().begin(), cenc_info.iv().end()),
|
||||
0, // No offset to start of media data in MP4 using CENC.
|
||||
cenc_info.subsamples));
|
||||
cenc_info.subsamples()));
|
||||
}
|
||||
|
||||
} // namespace mp4
|
||||
|
|
|
@ -82,7 +82,8 @@ class TrackRunIteratorTest : public testing::Test {
|
|||
moof.tracks.resize(2);
|
||||
moof.tracks[0].decode_time.decode_time = 0;
|
||||
moof.tracks[0].header.track_id = 1;
|
||||
moof.tracks[0].header.flags = kDefaultSampleFlagsPresentMask;
|
||||
moof.tracks[0].header.flags =
|
||||
TrackFragmentHeader::kDefaultSampleFlagsPresentMask;
|
||||
moof.tracks[0].header.default_sample_duration = 1024;
|
||||
moof.tracks[0].header.default_sample_size = 4;
|
||||
moof.tracks[0].runs.resize(2);
|
||||
|
@ -103,7 +104,8 @@ class TrackRunIteratorTest : public testing::Test {
|
|||
SetAscending(&moof.tracks[1].runs[0].sample_durations);
|
||||
moof.tracks[1].runs[0].sample_flags.resize(10);
|
||||
for (size_t i = 1; i < moof.tracks[1].runs[0].sample_flags.size(); i++) {
|
||||
moof.tracks[1].runs[0].sample_flags[i] = kNonKeySampleMask;
|
||||
moof.tracks[1].runs[0].sample_flags[i] =
|
||||
TrackFragmentHeader::kNonKeySampleMask;
|
||||
}
|
||||
|
||||
return moof;
|
||||
|
@ -211,7 +213,8 @@ TEST_F(TrackRunIteratorTest, BasicOperationTest) {
|
|||
TEST_F(TrackRunIteratorTest, TrackExtendsDefaultsTest) {
|
||||
moov_.extends.tracks[0].default_sample_duration = 50;
|
||||
moov_.extends.tracks[0].default_sample_size = 3;
|
||||
moov_.extends.tracks[0].default_sample_flags = kNonKeySampleMask;
|
||||
moov_.extends.tracks[0].default_sample_flags =
|
||||
TrackFragmentHeader::kNonKeySampleMask;
|
||||
iter_.reset(new TrackRunIterator(&moov_));
|
||||
MovieFragment moof = CreateFragment();
|
||||
moof.tracks[0].header.flags = 0;
|
||||
|
@ -233,8 +236,10 @@ TEST_F(TrackRunIteratorTest, FirstSampleFlagTest) {
|
|||
// defaults for all subsequent samples
|
||||
iter_.reset(new TrackRunIterator(&moov_));
|
||||
MovieFragment moof = CreateFragment();
|
||||
moof.tracks[1].header.flags = kDefaultSampleFlagsPresentMask;
|
||||
moof.tracks[1].header.default_sample_flags = kNonKeySampleMask;
|
||||
moof.tracks[1].header.flags =
|
||||
TrackFragmentHeader::kDefaultSampleFlagsPresentMask;
|
||||
moof.tracks[1].header.default_sample_flags =
|
||||
TrackFragmentHeader::kNonKeySampleMask;
|
||||
moof.tracks[1].runs[0].sample_flags.resize(1);
|
||||
ASSERT_TRUE(iter_->Init(moof));
|
||||
iter_->AdvanceRun();
|
||||
|
|
Loading…
Reference in New Issue