Adjust webm code for packager
- Adding namespace edash_packager - Fix includes - (u)int(8|16|32|64) to (u)int(8|16|32|64)_t - Remove MEDIA_EXPORT - Remove MediaLog Change-Id: Ifa116d966ab70ae1b3c299ae1f6f7044d7ae0cc6
This commit is contained in:
parent
87993c5dc7
commit
732e06fde0
|
@ -2,8 +2,9 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/base/text_track_config.h"
|
#include "packager/media/base/text_track_config.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
TextTrackConfig::TextTrackConfig()
|
TextTrackConfig::TextTrackConfig()
|
||||||
|
@ -28,3 +29,4 @@ bool TextTrackConfig::Matches(const TextTrackConfig& config) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -2,13 +2,12 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef MEDIA_BASE_TEXT_TRACK_CONFIG_H_
|
#ifndef PACKAGER_MEDIA_BASE_TEXT_TRACK_CONFIG_H_
|
||||||
#define MEDIA_BASE_TEXT_TRACK_CONFIG_H_
|
#define PACKAGER_MEDIA_BASE_TEXT_TRACK_CONFIG_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "media/base/media_export.h"
|
namespace edash_packager {
|
||||||
|
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
// Specifies the varieties of text tracks.
|
// Specifies the varieties of text tracks.
|
||||||
|
@ -20,7 +19,7 @@ enum TextKind {
|
||||||
kTextNone
|
kTextNone
|
||||||
};
|
};
|
||||||
|
|
||||||
class MEDIA_EXPORT TextTrackConfig {
|
class TextTrackConfig {
|
||||||
public:
|
public:
|
||||||
TextTrackConfig();
|
TextTrackConfig();
|
||||||
TextTrackConfig(TextKind kind,
|
TextTrackConfig(TextKind kind,
|
||||||
|
@ -44,5 +43,6 @@ class MEDIA_EXPORT TextTrackConfig {
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_BASE_TEXT_TRACK_H_
|
#endif // PACKAGER_MEDIA_BASE_TEXT_TRACK_H_
|
||||||
|
|
|
@ -2,11 +2,12 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef MEDIA_FILTERS_WEBVTT_UTIL_H_
|
#ifndef PACKAGER_MEDIA_FILTERS_WEBVTT_UTIL_H_
|
||||||
#define MEDIA_FILTERS_WEBVTT_UTIL_H_
|
#define PACKAGER_MEDIA_FILTERS_WEBVTT_UTIL_H_
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
// Utility function to create side data item for decoder buffer.
|
// Utility function to create side data item for decoder buffer.
|
||||||
|
@ -26,5 +27,6 @@ void MakeSideData(T id_begin, T id_end,
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FILTERS_WEBVTT_UTIL_H_
|
#endif // PACKAGER_MEDIA_FILTERS_WEBVTT_UTIL_H_
|
||||||
|
|
|
@ -2,42 +2,43 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/cluster_builder.h"
|
#include "packager/media/formats/webm/cluster_builder.h"
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "media/base/data_buffer.h"
|
#include "packager/media/base/data_buffer.h"
|
||||||
#include "media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
static const uint8 kClusterHeader[] = {
|
static const uint8_t kClusterHeader[] = {
|
||||||
0x1F, 0x43, 0xB6, 0x75, // CLUSTER ID
|
0x1F, 0x43, 0xB6, 0x75, // CLUSTER ID
|
||||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cluster(size = 0)
|
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cluster(size = 0)
|
||||||
0xE7, // Timecode ID
|
0xE7, // Timecode ID
|
||||||
0x88, // timecode(size=8)
|
0x88, // timecode(size=8)
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // timecode value
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // timecode value
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8 kSimpleBlockHeader[] = {
|
static const uint8_t kSimpleBlockHeader[] = {
|
||||||
0xA3, // SimpleBlock ID
|
0xA3, // SimpleBlock ID
|
||||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SimpleBlock(size = 0)
|
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SimpleBlock(size = 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8 kBlockGroupHeader[] = {
|
static const uint8_t kBlockGroupHeader[] = {
|
||||||
0xA0, // BlockGroup ID
|
0xA0, // BlockGroup ID
|
||||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // BlockGroup(size = 0)
|
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // BlockGroup(size = 0)
|
||||||
0x9B, // BlockDuration ID
|
0x9B, // BlockDuration ID
|
||||||
0x88, // BlockDuration(size = 8)
|
0x88, // BlockDuration(size = 8)
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // duration
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // duration
|
||||||
0xA1, // Block ID
|
0xA1, // Block ID
|
||||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Block(size = 0)
|
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Block(size = 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8 kBlockGroupHeaderWithoutBlockDuration[] = {
|
static const uint8_t kBlockGroupHeaderWithoutBlockDuration[] = {
|
||||||
0xA0, // BlockGroup ID
|
0xA0, // BlockGroup ID
|
||||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // BlockGroup(size = 0)
|
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // BlockGroup(size = 0)
|
||||||
0xA1, // Block ID
|
0xA1, // Block ID
|
||||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Block(size = 0)
|
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Block(size = 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -54,34 +55,37 @@ enum {
|
||||||
kInitialBufferSize = 32768,
|
kInitialBufferSize = 32768,
|
||||||
};
|
};
|
||||||
|
|
||||||
Cluster::Cluster(scoped_ptr<uint8[]> data, int size)
|
Cluster::Cluster(scoped_ptr<uint8_t[]> data, int size)
|
||||||
: data_(data.Pass()), size_(size) {}
|
: data_(data.Pass()), size_(size) {}
|
||||||
Cluster::~Cluster() {}
|
Cluster::~Cluster() {}
|
||||||
|
|
||||||
ClusterBuilder::ClusterBuilder() { Reset(); }
|
ClusterBuilder::ClusterBuilder() { Reset(); }
|
||||||
ClusterBuilder::~ClusterBuilder() {}
|
ClusterBuilder::~ClusterBuilder() {}
|
||||||
|
|
||||||
void ClusterBuilder::SetClusterTimecode(int64 cluster_timecode) {
|
void ClusterBuilder::SetClusterTimecode(int64_t cluster_timecode) {
|
||||||
DCHECK_EQ(cluster_timecode_, -1);
|
DCHECK_EQ(cluster_timecode_, -1);
|
||||||
|
|
||||||
cluster_timecode_ = cluster_timecode;
|
cluster_timecode_ = cluster_timecode;
|
||||||
|
|
||||||
// Write the timecode into the header.
|
// Write the timecode into the header.
|
||||||
uint8* buf = buffer_.get() + kClusterTimecodeOffset;
|
uint8_t* buf = buffer_.get() + kClusterTimecodeOffset;
|
||||||
for (int i = 7; i >= 0; --i) {
|
for (int i = 7; i >= 0; --i) {
|
||||||
buf[i] = cluster_timecode & 0xff;
|
buf[i] = cluster_timecode & 0xff;
|
||||||
cluster_timecode >>= 8;
|
cluster_timecode >>= 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClusterBuilder::AddSimpleBlock(int track_num, int64 timecode, int flags,
|
void ClusterBuilder::AddSimpleBlock(int track_num,
|
||||||
const uint8* data, int size) {
|
int64_t timecode,
|
||||||
|
int flags,
|
||||||
|
const uint8_t* data,
|
||||||
|
int size) {
|
||||||
int block_size = size + 4;
|
int block_size = size + 4;
|
||||||
int bytes_needed = sizeof(kSimpleBlockHeader) + block_size;
|
int bytes_needed = sizeof(kSimpleBlockHeader) + block_size;
|
||||||
if (bytes_needed > (buffer_size_ - bytes_used_))
|
if (bytes_needed > (buffer_size_ - bytes_used_))
|
||||||
ExtendBuffer(bytes_needed);
|
ExtendBuffer(bytes_needed);
|
||||||
|
|
||||||
uint8* buf = buffer_.get() + bytes_used_;
|
uint8_t* buf = buffer_.get() + bytes_used_;
|
||||||
int block_offset = bytes_used_;
|
int block_offset = bytes_used_;
|
||||||
memcpy(buf, kSimpleBlockHeader, sizeof(kSimpleBlockHeader));
|
memcpy(buf, kSimpleBlockHeader, sizeof(kSimpleBlockHeader));
|
||||||
UpdateUInt64(block_offset + kSimpleBlockSizeOffset, block_size);
|
UpdateUInt64(block_offset + kSimpleBlockSizeOffset, block_size);
|
||||||
|
@ -92,24 +96,30 @@ void ClusterBuilder::AddSimpleBlock(int track_num, int64 timecode, int flags,
|
||||||
bytes_used_ += bytes_needed;
|
bytes_used_ += bytes_needed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClusterBuilder::AddBlockGroup(int track_num, int64 timecode, int duration,
|
void ClusterBuilder::AddBlockGroup(int track_num,
|
||||||
int flags, const uint8* data, int size) {
|
int64_t timecode,
|
||||||
|
int duration,
|
||||||
|
int flags,
|
||||||
|
const uint8_t* data,
|
||||||
|
int size) {
|
||||||
AddBlockGroupInternal(track_num, timecode, true, duration, flags, data, size);
|
AddBlockGroupInternal(track_num, timecode, true, duration, flags, data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClusterBuilder::AddBlockGroupWithoutBlockDuration(int track_num,
|
void ClusterBuilder::AddBlockGroupWithoutBlockDuration(int track_num,
|
||||||
int64 timecode,
|
int64_t timecode,
|
||||||
int flags,
|
int flags,
|
||||||
const uint8* data,
|
const uint8_t* data,
|
||||||
int size) {
|
int size) {
|
||||||
AddBlockGroupInternal(track_num, timecode, false, 0, flags, data, size);
|
AddBlockGroupInternal(track_num, timecode, false, 0, flags, data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClusterBuilder::AddBlockGroupInternal(int track_num,
|
||||||
void ClusterBuilder::AddBlockGroupInternal(int track_num, int64 timecode,
|
int64_t timecode,
|
||||||
bool include_block_duration,
|
bool include_block_duration,
|
||||||
int duration, int flags,
|
int duration,
|
||||||
const uint8* data, int size) {
|
int flags,
|
||||||
|
const uint8_t* data,
|
||||||
|
int size) {
|
||||||
int block_size = size + 4;
|
int block_size = size + 4;
|
||||||
int bytes_needed = block_size;
|
int bytes_needed = block_size;
|
||||||
if (include_block_duration) {
|
if (include_block_duration) {
|
||||||
|
@ -123,7 +133,7 @@ void ClusterBuilder::AddBlockGroupInternal(int track_num, int64 timecode,
|
||||||
if (bytes_needed > (buffer_size_ - bytes_used_))
|
if (bytes_needed > (buffer_size_ - bytes_used_))
|
||||||
ExtendBuffer(bytes_needed);
|
ExtendBuffer(bytes_needed);
|
||||||
|
|
||||||
uint8* buf = buffer_.get() + bytes_used_;
|
uint8_t* buf = buffer_.get() + bytes_used_;
|
||||||
int block_group_offset = bytes_used_;
|
int block_group_offset = bytes_used_;
|
||||||
if (include_block_duration) {
|
if (include_block_duration) {
|
||||||
memcpy(buf, kBlockGroupHeader, sizeof(kBlockGroupHeader));
|
memcpy(buf, kBlockGroupHeader, sizeof(kBlockGroupHeader));
|
||||||
|
@ -150,8 +160,12 @@ void ClusterBuilder::AddBlockGroupInternal(int track_num, int64 timecode,
|
||||||
bytes_used_ += bytes_needed;
|
bytes_used_ += bytes_needed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClusterBuilder::WriteBlock(uint8* buf, int track_num, int64 timecode,
|
void ClusterBuilder::WriteBlock(uint8_t* buf,
|
||||||
int flags, const uint8* data, int size) {
|
int track_num,
|
||||||
|
int64_t timecode,
|
||||||
|
int flags,
|
||||||
|
const uint8_t* data,
|
||||||
|
int size) {
|
||||||
DCHECK_GE(track_num, 0);
|
DCHECK_GE(track_num, 0);
|
||||||
DCHECK_LE(track_num, 126);
|
DCHECK_LE(track_num, 126);
|
||||||
DCHECK_GE(flags, 0);
|
DCHECK_GE(flags, 0);
|
||||||
|
@ -160,7 +174,7 @@ void ClusterBuilder::WriteBlock(uint8* buf, int track_num, int64 timecode,
|
||||||
DCHECK_GT(size, 0);
|
DCHECK_GT(size, 0);
|
||||||
DCHECK_NE(cluster_timecode_, -1);
|
DCHECK_NE(cluster_timecode_, -1);
|
||||||
|
|
||||||
int64 timecode_delta = timecode - cluster_timecode_;
|
int64_t timecode_delta = timecode - cluster_timecode_;
|
||||||
DCHECK_GE(timecode_delta, -32768);
|
DCHECK_GE(timecode_delta, -32768);
|
||||||
DCHECK_LE(timecode_delta, 32767);
|
DCHECK_LE(timecode_delta, 32767);
|
||||||
|
|
||||||
|
@ -193,7 +207,7 @@ scoped_ptr<Cluster> ClusterBuilder::FinishWithUnknownSize() {
|
||||||
|
|
||||||
void ClusterBuilder::Reset() {
|
void ClusterBuilder::Reset() {
|
||||||
buffer_size_ = kInitialBufferSize;
|
buffer_size_ = kInitialBufferSize;
|
||||||
buffer_.reset(new uint8[buffer_size_]);
|
buffer_.reset(new uint8_t[buffer_size_]);
|
||||||
memcpy(buffer_.get(), kClusterHeader, sizeof(kClusterHeader));
|
memcpy(buffer_.get(), kClusterHeader, sizeof(kClusterHeader));
|
||||||
bytes_used_ = sizeof(kClusterHeader);
|
bytes_used_ = sizeof(kClusterHeader);
|
||||||
cluster_timecode_ = -1;
|
cluster_timecode_ = -1;
|
||||||
|
@ -205,16 +219,16 @@ void ClusterBuilder::ExtendBuffer(int bytes_needed) {
|
||||||
while ((new_buffer_size - bytes_used_) < bytes_needed)
|
while ((new_buffer_size - bytes_used_) < bytes_needed)
|
||||||
new_buffer_size *= 2;
|
new_buffer_size *= 2;
|
||||||
|
|
||||||
scoped_ptr<uint8[]> new_buffer(new uint8[new_buffer_size]);
|
scoped_ptr<uint8_t[]> new_buffer(new uint8_t[new_buffer_size]);
|
||||||
|
|
||||||
memcpy(new_buffer.get(), buffer_.get(), bytes_used_);
|
memcpy(new_buffer.get(), buffer_.get(), bytes_used_);
|
||||||
buffer_.reset(new_buffer.release());
|
buffer_.reset(new_buffer.release());
|
||||||
buffer_size_ = new_buffer_size;
|
buffer_size_ = new_buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClusterBuilder::UpdateUInt64(int offset, int64 value) {
|
void ClusterBuilder::UpdateUInt64(int offset, int64_t value) {
|
||||||
DCHECK_LE(offset + 7, buffer_size_);
|
DCHECK_LE(offset + 7, buffer_size_);
|
||||||
uint8* buf = buffer_.get() + offset;
|
uint8_t* buf = buffer_.get() + offset;
|
||||||
|
|
||||||
// Fill the last 7 bytes of size field in big-endian order.
|
// Fill the last 7 bytes of size field in big-endian order.
|
||||||
for (int i = 7; i > 0; i--) {
|
for (int i = 7; i > 0; i--) {
|
||||||
|
@ -224,3 +238,4 @@ void ClusterBuilder::UpdateUInt64(int offset, int64 value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -5,21 +5,22 @@
|
||||||
#ifndef MEDIA_FORMATS_WEBM_CLUSTER_BUILDER_H_
|
#ifndef MEDIA_FORMATS_WEBM_CLUSTER_BUILDER_H_
|
||||||
#define MEDIA_FORMATS_WEBM_CLUSTER_BUILDER_H_
|
#define MEDIA_FORMATS_WEBM_CLUSTER_BUILDER_H_
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include <stdint.h>
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
class Cluster {
|
class Cluster {
|
||||||
public:
|
public:
|
||||||
Cluster(scoped_ptr<uint8[]> data, int size);
|
Cluster(scoped_ptr<uint8_t[]> data, int size);
|
||||||
~Cluster();
|
~Cluster();
|
||||||
|
|
||||||
const uint8* data() const { return data_.get(); }
|
const uint8_t* data() const { return data_.get(); }
|
||||||
int size() const { return size_; }
|
int size() const { return size_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
scoped_ptr<uint8[]> data_;
|
scoped_ptr<uint8_t[]> data_;
|
||||||
int size_;
|
int size_;
|
||||||
|
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(Cluster);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(Cluster);
|
||||||
|
@ -30,35 +31,54 @@ class ClusterBuilder {
|
||||||
ClusterBuilder();
|
ClusterBuilder();
|
||||||
~ClusterBuilder();
|
~ClusterBuilder();
|
||||||
|
|
||||||
void SetClusterTimecode(int64 cluster_timecode);
|
void SetClusterTimecode(int64_t cluster_timecode);
|
||||||
void AddSimpleBlock(int track_num, int64 timecode, int flags,
|
void AddSimpleBlock(int track_num,
|
||||||
const uint8* data, int size);
|
int64_t timecode,
|
||||||
void AddBlockGroup(int track_num, int64 timecode, int duration, int flags,
|
int flags,
|
||||||
const uint8* data, int size);
|
const uint8_t* data,
|
||||||
void AddBlockGroupWithoutBlockDuration(int track_num, int64 timecode,
|
int size);
|
||||||
int flags, const uint8* data, int size);
|
void AddBlockGroup(int track_num,
|
||||||
|
int64_t timecode,
|
||||||
|
int duration,
|
||||||
|
int flags,
|
||||||
|
const uint8_t* data,
|
||||||
|
int size);
|
||||||
|
void AddBlockGroupWithoutBlockDuration(int track_num,
|
||||||
|
int64_t timecode,
|
||||||
|
int flags,
|
||||||
|
const uint8_t* data,
|
||||||
|
int size);
|
||||||
|
|
||||||
scoped_ptr<Cluster> Finish();
|
scoped_ptr<Cluster> Finish();
|
||||||
scoped_ptr<Cluster> FinishWithUnknownSize();
|
scoped_ptr<Cluster> FinishWithUnknownSize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AddBlockGroupInternal(int track_num, int64 timecode,
|
void AddBlockGroupInternal(int track_num,
|
||||||
bool include_block_duration, int duration,
|
int64_t timecode,
|
||||||
int flags, const uint8* data, int size);
|
bool include_block_duration,
|
||||||
|
int duration,
|
||||||
|
int flags,
|
||||||
|
const uint8_t* data,
|
||||||
|
int size);
|
||||||
void Reset();
|
void Reset();
|
||||||
void ExtendBuffer(int bytes_needed);
|
void ExtendBuffer(int bytes_needed);
|
||||||
void UpdateUInt64(int offset, int64 value);
|
void UpdateUInt64(int offset, int64_t value);
|
||||||
void WriteBlock(uint8* buf, int track_num, int64 timecode, int flags,
|
void WriteBlock(uint8_t* buf,
|
||||||
const uint8* data, int size);
|
int track_num,
|
||||||
|
int64_t timecode,
|
||||||
|
int flags,
|
||||||
|
const uint8_t* data,
|
||||||
|
int size);
|
||||||
|
|
||||||
scoped_ptr<uint8[]> buffer_;
|
scoped_ptr<uint8_t[]> buffer_;
|
||||||
int buffer_size_;
|
int buffer_size_;
|
||||||
int bytes_used_;
|
int bytes_used_;
|
||||||
int64 cluster_timecode_;
|
int64_t cluster_timecode_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ClusterBuilder);
|
DISALLOW_COPY_AND_ASSIGN(ClusterBuilder);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_CLUSTER_BUILDER_H_
|
#endif // MEDIA_FORMATS_WEBM_CLUSTER_BUILDER_H_
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "media/formats/webm/opus_packet_builder.h"
|
#include "packager/media/formats/webm/opus_packet_builder.h"
|
||||||
#include "media/formats/webm/webm_cluster_parser.h"
|
#include "packager/media/formats/webm/webm_cluster_parser.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
OpusPacket::OpusPacket(uint8_t config, uint8_t frame_count, bool is_VBR) {
|
OpusPacket::OpusPacket(uint8_t config, uint8_t frame_count, bool is_VBR) {
|
||||||
|
@ -87,3 +88,4 @@ ScopedVector<OpusPacket> BuildAllOpusPackets() {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -7,9 +7,10 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
#include "base/memory/scoped_vector.h"
|
#include "packager/base/memory/scoped_vector.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
// From Opus RFC. See https://tools.ietf.org/html/rfc6716#page-14
|
// From Opus RFC. See https://tools.ietf.org/html/rfc6716#page-14
|
||||||
|
@ -39,5 +40,6 @@ class OpusPacket {
|
||||||
ScopedVector<OpusPacket> BuildAllOpusPackets();
|
ScopedVector<OpusPacket> BuildAllOpusPackets();
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_OPUS_PACKET_BUILDER_H_
|
#endif // MEDIA_FORMATS_WEBM_OPUS_PACKET_BUILDER_H_
|
||||||
|
|
|
@ -2,15 +2,16 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/tracks_builder.h"
|
#include "packager/media/formats/webm/tracks_builder.h"
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
// Returns size of an integer, formatted using Matroska serialization.
|
// Returns size of an integer, formatted using Matroska serialization.
|
||||||
static int GetUIntMkvSize(uint64 value) {
|
static int GetUIntMkvSize(uint64_t value) {
|
||||||
if (value < 0x07FULL)
|
if (value < 0x07FULL)
|
||||||
return 1;
|
return 1;
|
||||||
if (value < 0x03FFFULL)
|
if (value < 0x03FFFULL)
|
||||||
|
@ -29,7 +30,7 @@ static int GetUIntMkvSize(uint64 value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the minimium size required to serialize an integer value.
|
// Returns the minimium size required to serialize an integer value.
|
||||||
static int GetUIntSize(uint64 value) {
|
static int GetUIntSize(uint64_t value) {
|
||||||
if (value < 0x0100ULL)
|
if (value < 0x0100ULL)
|
||||||
return 1;
|
return 1;
|
||||||
if (value < 0x010000ULL)
|
if (value < 0x010000ULL)
|
||||||
|
@ -51,7 +52,7 @@ static int MasterElementSize(int element_id, int payload_size) {
|
||||||
return GetUIntSize(element_id) + GetUIntMkvSize(payload_size) + payload_size;
|
return GetUIntSize(element_id) + GetUIntMkvSize(payload_size) + payload_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int UIntElementSize(int element_id, uint64 value) {
|
static int UIntElementSize(int element_id, uint64_t value) {
|
||||||
return GetUIntSize(element_id) + 1 + GetUIntSize(value);
|
return GetUIntSize(element_id) + 1 + GetUIntSize(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,23 +66,26 @@ static int StringElementSize(int element_id, const std::string& value) {
|
||||||
value.length();
|
value.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeInt(uint8** buf_ptr, int* buf_size_ptr,
|
static void SerializeInt(uint8_t** buf_ptr,
|
||||||
int64 value, int size) {
|
int* buf_size_ptr,
|
||||||
uint8*& buf = *buf_ptr;
|
int64_t value,
|
||||||
|
int size) {
|
||||||
|
uint8_t*& buf = *buf_ptr;
|
||||||
int& buf_size = *buf_size_ptr;
|
int& buf_size = *buf_size_ptr;
|
||||||
|
|
||||||
for (int idx = 1; idx <= size; ++idx) {
|
for (int idx = 1; idx <= size; ++idx) {
|
||||||
*buf++ = static_cast<uint8>(value >> ((size - idx) * 8));
|
*buf++ = static_cast<uint8_t>(value >> ((size - idx) * 8));
|
||||||
--buf_size;
|
--buf_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeDouble(uint8** buf_ptr, int* buf_size_ptr,
|
static void SerializeDouble(uint8_t** buf_ptr,
|
||||||
|
int* buf_size_ptr,
|
||||||
double value) {
|
double value) {
|
||||||
// Use a union to convert |value| to native endian integer bit pattern.
|
// Use a union to convert |value| to native endian integer bit pattern.
|
||||||
union {
|
union {
|
||||||
double src;
|
double src;
|
||||||
int64 dst;
|
int64_t dst;
|
||||||
} tmp;
|
} tmp;
|
||||||
tmp.src = value;
|
tmp.src = value;
|
||||||
|
|
||||||
|
@ -89,26 +93,28 @@ static void SerializeDouble(uint8** buf_ptr, int* buf_size_ptr,
|
||||||
SerializeInt(buf_ptr, buf_size_ptr, tmp.dst, 8);
|
SerializeInt(buf_ptr, buf_size_ptr, tmp.dst, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteElementId(uint8** buf, int* buf_size, int element_id) {
|
static void WriteElementId(uint8_t** buf, int* buf_size, int element_id) {
|
||||||
SerializeInt(buf, buf_size, element_id, GetUIntSize(element_id));
|
SerializeInt(buf, buf_size, element_id, GetUIntSize(element_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteUInt(uint8** buf, int* buf_size, uint64 value) {
|
static void WriteUInt(uint8_t** buf, int* buf_size, uint64_t value) {
|
||||||
const int size = GetUIntMkvSize(value);
|
const int size = GetUIntMkvSize(value);
|
||||||
value |= (1ULL << (size * 7)); // Matroska formatting
|
value |= (1ULL << (size * 7)); // Matroska formatting
|
||||||
SerializeInt(buf, buf_size, value, size);
|
SerializeInt(buf, buf_size, value, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteMasterElement(uint8** buf, int* buf_size,
|
static void WriteMasterElement(uint8_t** buf,
|
||||||
int element_id, int payload_size) {
|
int* buf_size,
|
||||||
|
int element_id,
|
||||||
|
int payload_size) {
|
||||||
WriteElementId(buf, buf_size, element_id);
|
WriteElementId(buf, buf_size, element_id);
|
||||||
WriteUInt(buf, buf_size, payload_size);
|
WriteUInt(buf, buf_size, payload_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteUIntElement(uint8** buf,
|
static void WriteUIntElement(uint8_t** buf,
|
||||||
int* buf_size,
|
int* buf_size,
|
||||||
int element_id,
|
int element_id,
|
||||||
uint64 value) {
|
uint64_t value) {
|
||||||
WriteElementId(buf, buf_size, element_id);
|
WriteElementId(buf, buf_size, element_id);
|
||||||
|
|
||||||
const int size = GetUIntSize(value);
|
const int size = GetUIntSize(value);
|
||||||
|
@ -117,21 +123,25 @@ static void WriteUIntElement(uint8** buf,
|
||||||
SerializeInt(buf, buf_size, value, size);
|
SerializeInt(buf, buf_size, value, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteDoubleElement(uint8** buf, int* buf_size,
|
static void WriteDoubleElement(uint8_t** buf,
|
||||||
int element_id, double value) {
|
int* buf_size,
|
||||||
|
int element_id,
|
||||||
|
double value) {
|
||||||
WriteElementId(buf, buf_size, element_id);
|
WriteElementId(buf, buf_size, element_id);
|
||||||
WriteUInt(buf, buf_size, 8);
|
WriteUInt(buf, buf_size, 8);
|
||||||
SerializeDouble(buf, buf_size, value);
|
SerializeDouble(buf, buf_size, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteStringElement(uint8** buf_ptr, int* buf_size_ptr,
|
static void WriteStringElement(uint8_t** buf_ptr,
|
||||||
int element_id, const std::string& value) {
|
int* buf_size_ptr,
|
||||||
uint8*& buf = *buf_ptr;
|
int element_id,
|
||||||
|
const std::string& value) {
|
||||||
|
uint8_t*& buf = *buf_ptr;
|
||||||
int& buf_size = *buf_size_ptr;
|
int& buf_size = *buf_size_ptr;
|
||||||
|
|
||||||
WriteElementId(&buf, &buf_size, element_id);
|
WriteElementId(&buf, &buf_size, element_id);
|
||||||
|
|
||||||
const uint64 size = value.length();
|
const uint64_t size = value.length();
|
||||||
WriteUInt(&buf, &buf_size, size);
|
WriteUInt(&buf, &buf_size, size);
|
||||||
|
|
||||||
memcpy(buf, value.data(), size);
|
memcpy(buf, value.data(), size);
|
||||||
|
@ -146,7 +156,7 @@ TracksBuilder::TracksBuilder()
|
||||||
TracksBuilder::~TracksBuilder() {}
|
TracksBuilder::~TracksBuilder() {}
|
||||||
|
|
||||||
void TracksBuilder::AddVideoTrack(int track_num,
|
void TracksBuilder::AddVideoTrack(int track_num,
|
||||||
uint64 track_uid,
|
uint64_t track_uid,
|
||||||
const std::string& codec_id,
|
const std::string& codec_id,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& language,
|
const std::string& language,
|
||||||
|
@ -159,7 +169,7 @@ void TracksBuilder::AddVideoTrack(int track_num,
|
||||||
}
|
}
|
||||||
|
|
||||||
void TracksBuilder::AddAudioTrack(int track_num,
|
void TracksBuilder::AddAudioTrack(int track_num,
|
||||||
uint64 track_uid,
|
uint64_t track_uid,
|
||||||
const std::string& codec_id,
|
const std::string& codec_id,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& language,
|
const std::string& language,
|
||||||
|
@ -172,7 +182,7 @@ void TracksBuilder::AddAudioTrack(int track_num,
|
||||||
}
|
}
|
||||||
|
|
||||||
void TracksBuilder::AddTextTrack(int track_num,
|
void TracksBuilder::AddTextTrack(int track_num,
|
||||||
uint64 track_uid,
|
uint64_t track_uid,
|
||||||
const std::string& codec_id,
|
const std::string& codec_id,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& language) {
|
const std::string& language) {
|
||||||
|
@ -180,9 +190,9 @@ void TracksBuilder::AddTextTrack(int track_num,
|
||||||
codec_id, name, language, -1, -1, -1, -1, -1);
|
codec_id, name, language, -1, -1, -1, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8> TracksBuilder::Finish() {
|
std::vector<uint8_t> TracksBuilder::Finish() {
|
||||||
// Allocate the storage
|
// Allocate the storage
|
||||||
std::vector<uint8> buffer;
|
std::vector<uint8_t> buffer;
|
||||||
buffer.resize(GetTracksSize());
|
buffer.resize(GetTracksSize());
|
||||||
|
|
||||||
// Populate the storage with a tracks header
|
// Populate the storage with a tracks header
|
||||||
|
@ -193,7 +203,7 @@ std::vector<uint8> TracksBuilder::Finish() {
|
||||||
|
|
||||||
void TracksBuilder::AddTrackInternal(int track_num,
|
void TracksBuilder::AddTrackInternal(int track_num,
|
||||||
int track_type,
|
int track_type,
|
||||||
uint64 track_uid,
|
uint64_t track_uid,
|
||||||
const std::string& codec_id,
|
const std::string& codec_id,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& language,
|
const std::string& language,
|
||||||
|
@ -223,7 +233,7 @@ int TracksBuilder::GetTracksPayloadSize() const {
|
||||||
return payload_size;
|
return payload_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TracksBuilder::WriteTracks(uint8* buf, int buf_size) const {
|
void TracksBuilder::WriteTracks(uint8_t* buf, int buf_size) const {
|
||||||
WriteMasterElement(&buf, &buf_size, kWebMIdTracks, GetTracksPayloadSize());
|
WriteMasterElement(&buf, &buf_size, kWebMIdTracks, GetTracksPayloadSize());
|
||||||
|
|
||||||
for (TrackList::const_iterator itr = tracks_.begin();
|
for (TrackList::const_iterator itr = tracks_.begin();
|
||||||
|
@ -234,7 +244,7 @@ void TracksBuilder::WriteTracks(uint8* buf, int buf_size) const {
|
||||||
|
|
||||||
TracksBuilder::Track::Track(int track_num,
|
TracksBuilder::Track::Track(int track_num,
|
||||||
int track_type,
|
int track_type,
|
||||||
uint64 track_uid,
|
uint64_t track_uid,
|
||||||
const std::string& codec_id,
|
const std::string& codec_id,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& language,
|
const std::string& language,
|
||||||
|
@ -341,7 +351,7 @@ int TracksBuilder::Track::GetPayloadSize() const {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TracksBuilder::Track::Write(uint8** buf, int* buf_size) const {
|
void TracksBuilder::Track::Write(uint8_t** buf, int* buf_size) const {
|
||||||
WriteMasterElement(buf, buf_size, kWebMIdTrackEntry, GetPayloadSize());
|
WriteMasterElement(buf, buf_size, kWebMIdTrackEntry, GetPayloadSize());
|
||||||
|
|
||||||
WriteUIntElement(buf, buf_size, kWebMIdTrackNumber, track_num_);
|
WriteUIntElement(buf, buf_size, kWebMIdTrackNumber, track_num_);
|
||||||
|
@ -384,3 +394,4 @@ void TracksBuilder::Track::Write(uint8** buf, int* buf_size) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -5,12 +5,15 @@
|
||||||
#ifndef MEDIA_FORMATS_WEBM_TRACKS_BUILDER_H_
|
#ifndef MEDIA_FORMATS_WEBM_TRACKS_BUILDER_H_
|
||||||
#define MEDIA_FORMATS_WEBM_TRACKS_BUILDER_H_
|
#define MEDIA_FORMATS_WEBM_TRACKS_BUILDER_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "packager/base/macros.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
class TracksBuilder {
|
class TracksBuilder {
|
||||||
|
@ -28,7 +31,7 @@ class TracksBuilder {
|
||||||
// DefaultDuration. Similar applies to |audio_channels|,
|
// DefaultDuration. Similar applies to |audio_channels|,
|
||||||
// |audio_sampling_frequency|, |video_pixel_width| and |video_pixel_height|.
|
// |audio_sampling_frequency|, |video_pixel_width| and |video_pixel_height|.
|
||||||
void AddVideoTrack(int track_num,
|
void AddVideoTrack(int track_num,
|
||||||
uint64 track_uid,
|
uint64_t track_uid,
|
||||||
const std::string& codec_id,
|
const std::string& codec_id,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& language,
|
const std::string& language,
|
||||||
|
@ -36,7 +39,7 @@ class TracksBuilder {
|
||||||
int video_pixel_width,
|
int video_pixel_width,
|
||||||
int video_pixel_height);
|
int video_pixel_height);
|
||||||
void AddAudioTrack(int track_num,
|
void AddAudioTrack(int track_num,
|
||||||
uint64 track_uid,
|
uint64_t track_uid,
|
||||||
const std::string& codec_id,
|
const std::string& codec_id,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& language,
|
const std::string& language,
|
||||||
|
@ -44,17 +47,17 @@ class TracksBuilder {
|
||||||
int audio_channels,
|
int audio_channels,
|
||||||
double audio_sampling_frequency);
|
double audio_sampling_frequency);
|
||||||
void AddTextTrack(int track_num,
|
void AddTextTrack(int track_num,
|
||||||
uint64 track_uid,
|
uint64_t track_uid,
|
||||||
const std::string& codec_id,
|
const std::string& codec_id,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& language);
|
const std::string& language);
|
||||||
|
|
||||||
std::vector<uint8> Finish();
|
std::vector<uint8_t> Finish();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AddTrackInternal(int track_num,
|
void AddTrackInternal(int track_num,
|
||||||
int track_type,
|
int track_type,
|
||||||
uint64 track_uid,
|
uint64_t track_uid,
|
||||||
const std::string& codec_id,
|
const std::string& codec_id,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& language,
|
const std::string& language,
|
||||||
|
@ -65,13 +68,13 @@ class TracksBuilder {
|
||||||
double audio_sampling_frequency);
|
double audio_sampling_frequency);
|
||||||
int GetTracksSize() const;
|
int GetTracksSize() const;
|
||||||
int GetTracksPayloadSize() const;
|
int GetTracksPayloadSize() const;
|
||||||
void WriteTracks(uint8* buffer, int buffer_size) const;
|
void WriteTracks(uint8_t* buffer, int buffer_size) const;
|
||||||
|
|
||||||
class Track {
|
class Track {
|
||||||
public:
|
public:
|
||||||
Track(int track_num,
|
Track(int track_num,
|
||||||
int track_type,
|
int track_type,
|
||||||
uint64 track_uid,
|
uint64_t track_uid,
|
||||||
const std::string& codec_id,
|
const std::string& codec_id,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& language,
|
const std::string& language,
|
||||||
|
@ -83,7 +86,8 @@ class TracksBuilder {
|
||||||
bool allow_invalid_values);
|
bool allow_invalid_values);
|
||||||
|
|
||||||
int GetSize() const;
|
int GetSize() const;
|
||||||
void Write(uint8** buf, int* buf_size) const;
|
void Write(uint8_t** buf, int* buf_size) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int GetPayloadSize() const;
|
int GetPayloadSize() const;
|
||||||
int GetVideoPayloadSize() const;
|
int GetVideoPayloadSize() const;
|
||||||
|
@ -110,5 +114,6 @@ class TracksBuilder {
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_TRACKS_BUILDER_H_
|
#endif // MEDIA_FORMATS_WEBM_TRACKS_BUILDER_H_
|
||||||
|
|
|
@ -2,16 +2,16 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/webm_audio_client.h"
|
#include "packager/media/formats/webm/webm_audio_client.h"
|
||||||
|
|
||||||
#include "media/base/audio_decoder_config.h"
|
#include "packager/media/base/audio_decoder_config.h"
|
||||||
#include "media/base/channel_layout.h"
|
#include "packager/media/base/channel_layout.h"
|
||||||
#include "media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
WebMAudioClient::WebMAudioClient(const scoped_refptr<MediaLog>& media_log)
|
WebMAudioClient::WebMAudioClient() {
|
||||||
: media_log_(media_log) {
|
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,8 +25,11 @@ void WebMAudioClient::Reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMAudioClient::InitializeConfig(
|
bool WebMAudioClient::InitializeConfig(
|
||||||
const std::string& codec_id, const std::vector<uint8>& codec_private,
|
const std::string& codec_id,
|
||||||
int64 seek_preroll, int64 codec_delay, bool is_encrypted,
|
const std::vector<uint8_t>& codec_private,
|
||||||
|
int64_t seek_preroll,
|
||||||
|
int64_t codec_delay,
|
||||||
|
bool is_encrypted,
|
||||||
AudioDecoderConfig* config) {
|
AudioDecoderConfig* config) {
|
||||||
DCHECK(config);
|
DCHECK(config);
|
||||||
SampleFormat sample_format = kSampleFormatPlanarF32;
|
SampleFormat sample_format = kSampleFormatPlanarF32;
|
||||||
|
@ -37,7 +40,7 @@ bool WebMAudioClient::InitializeConfig(
|
||||||
} else if (codec_id == "A_OPUS") {
|
} else if (codec_id == "A_OPUS") {
|
||||||
audio_codec = kCodecOpus;
|
audio_codec = kCodecOpus;
|
||||||
} else {
|
} else {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unsupported audio codec_id " << codec_id;
|
LOG(ERROR) << "Unsupported audio codec_id " << codec_id;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +54,7 @@ bool WebMAudioClient::InitializeConfig(
|
||||||
ChannelLayout channel_layout = GuessChannelLayout(channels_);
|
ChannelLayout channel_layout = GuessChannelLayout(channels_);
|
||||||
|
|
||||||
if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) {
|
if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unsupported channel count " << channels_;
|
LOG(ERROR) << "Unsupported channel count " << channels_;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +69,7 @@ bool WebMAudioClient::InitializeConfig(
|
||||||
sample_format = kSampleFormatF32;
|
sample_format = kSampleFormatF32;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8* extra_data = NULL;
|
const uint8_t* extra_data = NULL;
|
||||||
size_t extra_data_size = 0;
|
size_t extra_data_size = 0;
|
||||||
if (codec_private.size() > 0) {
|
if (codec_private.size() > 0) {
|
||||||
extra_data = &codec_private[0];
|
extra_data = &codec_private[0];
|
||||||
|
@ -96,12 +99,11 @@ bool WebMAudioClient::InitializeConfig(
|
||||||
return config->IsValidConfig();
|
return config->IsValidConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMAudioClient::OnUInt(int id, int64 val) {
|
bool WebMAudioClient::OnUInt(int id, int64_t val) {
|
||||||
if (id == kWebMIdChannels) {
|
if (id == kWebMIdChannels) {
|
||||||
if (channels_ != -1) {
|
if (channels_ != -1) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Multiple values for id " << std::hex
|
LOG(ERROR) << "Multiple values for id " << std::hex << id
|
||||||
<< id << " specified. (" << channels_
|
<< " specified. (" << channels_ << " and " << val << ")";
|
||||||
<< " and " << val << ")";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,9 +130,8 @@ bool WebMAudioClient::OnFloat(int id, double val) {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (*dst != -1) {
|
if (*dst != -1) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Multiple values for id " << std::hex << id
|
LOG(ERROR) << "Multiple values for id " << std::hex << id << " specified ("
|
||||||
<< " specified (" << *dst << " and " << val
|
<< *dst << " and " << val << ")";
|
||||||
<< ")";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,3 +140,4 @@ bool WebMAudioClient::OnFloat(int id, double val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -8,16 +8,16 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "media/base/media_log.h"
|
#include "packager/media/formats/webm/webm_parser.h"
|
||||||
#include "media/formats/webm/webm_parser.h"
|
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
class AudioDecoderConfig;
|
class AudioDecoderConfig;
|
||||||
|
|
||||||
// Helper class used to parse an Audio element inside a TrackEntry element.
|
// Helper class used to parse an Audio element inside a TrackEntry element.
|
||||||
class WebMAudioClient : public WebMParserClient {
|
class WebMAudioClient : public WebMParserClient {
|
||||||
public:
|
public:
|
||||||
explicit WebMAudioClient(const scoped_refptr<MediaLog>& media_log);
|
WebMAudioClient();
|
||||||
~WebMAudioClient() override;
|
~WebMAudioClient() override;
|
||||||
|
|
||||||
// Reset this object's state so it can process a new audio track element.
|
// Reset this object's state so it can process a new audio track element.
|
||||||
|
@ -30,18 +30,17 @@ class WebMAudioClient : public WebMParserClient {
|
||||||
// Returns false if there was unexpected values in the provided parameters or
|
// Returns false if there was unexpected values in the provided parameters or
|
||||||
// audio track element fields.
|
// audio track element fields.
|
||||||
bool InitializeConfig(const std::string& codec_id,
|
bool InitializeConfig(const std::string& codec_id,
|
||||||
const std::vector<uint8>& codec_private,
|
const std::vector<uint8_t>& codec_private,
|
||||||
const int64 seek_preroll,
|
const int64_t seek_preroll,
|
||||||
const int64 codec_delay,
|
const int64_t codec_delay,
|
||||||
bool is_encrypted,
|
bool is_encrypted,
|
||||||
AudioDecoderConfig* config);
|
AudioDecoderConfig* config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// WebMParserClient implementation.
|
// WebMParserClient implementation.
|
||||||
bool OnUInt(int id, int64 val) override;
|
bool OnUInt(int id, int64_t val) override;
|
||||||
bool OnFloat(int id, double val) override;
|
bool OnFloat(int id, double val) override;
|
||||||
|
|
||||||
scoped_refptr<MediaLog> media_log_;
|
|
||||||
int channels_;
|
int channels_;
|
||||||
double samples_per_second_;
|
double samples_per_second_;
|
||||||
double output_samples_per_second_;
|
double output_samples_per_second_;
|
||||||
|
@ -50,5 +49,6 @@ class WebMAudioClient : public WebMParserClient {
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_WEBM_AUDIO_CLIENT_H_
|
#endif // MEDIA_FORMATS_WEBM_WEBM_AUDIO_CLIENT_H_
|
||||||
|
|
|
@ -2,19 +2,35 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/webm_cluster_parser.h"
|
#include "packager/media/formats/webm/webm_cluster_parser.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "base/sys_byteorder.h"
|
#include "packager/base/sys_byteorder.h"
|
||||||
#include "media/base/decrypt_config.h"
|
#include "packager/media/base/decrypt_config.h"
|
||||||
#include "media/base/timestamp_constants.h"
|
#include "packager/media/base/timestamp_constants.h"
|
||||||
#include "media/filters/webvtt_util.h"
|
#include "packager/media/filters/webvtt_util.h"
|
||||||
#include "media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
#include "media/formats/webm/webm_crypto_helpers.h"
|
#include "packager/media/formats/webm/webm_crypto_helpers.h"
|
||||||
#include "media/formats/webm/webm_webvtt_parser.h"
|
#include "packager/media/formats/webm/webm_webvtt_parser.h"
|
||||||
|
|
||||||
|
// Logs only while |count| < |max|, increments |count| for each log, and warns
|
||||||
|
// in the log if |count| has just reached |max|.
|
||||||
|
#define LIMITED_LOG(level, count, max) \
|
||||||
|
LOG_IF(level, (count) < (max)) \
|
||||||
|
<< (((count) + 1 == (max)) \
|
||||||
|
? "(Log limit reached. Further similar entries " \
|
||||||
|
"may be suppressed): " \
|
||||||
|
: "")
|
||||||
|
#define LIMITED_DLOG(level, count, max) \
|
||||||
|
DLOG_IF(level, (count) < (max)) \
|
||||||
|
<< (((count) + 1 == (max)) \
|
||||||
|
? "(Log limit reached. Further similar entries " \
|
||||||
|
"may be suppressed): " \
|
||||||
|
: "")
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
const uint16_t WebMClusterParser::kOpusFrameDurationsMu[] = {
|
const uint16_t WebMClusterParser::kOpusFrameDurationsMu[] = {
|
||||||
|
@ -23,26 +39,25 @@ const uint16_t WebMClusterParser::kOpusFrameDurationsMu[] = {
|
||||||
10000, 20000, 2500, 5000, 10000, 20000, 2500, 5000, 10000, 20000};
|
10000, 20000, 2500, 5000, 10000, 20000, 2500, 5000, 10000, 20000};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// Limits the number of MEDIA_LOG() calls in the path of reading encoded
|
// Limits the number of LOG() calls in the path of reading encoded
|
||||||
// duration to avoid spamming for corrupted data.
|
// duration to avoid spamming for corrupted data.
|
||||||
kMaxDurationErrorLogs = 10,
|
kMaxDurationErrorLogs = 10,
|
||||||
// Limits the number of MEDIA_LOG() calls warning the user that buffer
|
// Limits the number of LOG() calls warning the user that buffer
|
||||||
// durations have been estimated.
|
// durations have been estimated.
|
||||||
kMaxDurationEstimateLogs = 10,
|
kMaxDurationEstimateLogs = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
WebMClusterParser::WebMClusterParser(
|
WebMClusterParser::WebMClusterParser(
|
||||||
int64 timecode_scale,
|
int64_t timecode_scale,
|
||||||
int audio_track_num,
|
int audio_track_num,
|
||||||
base::TimeDelta audio_default_duration,
|
base::TimeDelta audio_default_duration,
|
||||||
int video_track_num,
|
int video_track_num,
|
||||||
base::TimeDelta video_default_duration,
|
base::TimeDelta video_default_duration,
|
||||||
const WebMTracksParser::TextTracks& text_tracks,
|
const WebMTracksParser::TextTracks& text_tracks,
|
||||||
const std::set<int64>& ignored_tracks,
|
const std::set<int64_t>& ignored_tracks,
|
||||||
const std::string& audio_encryption_key_id,
|
const std::string& audio_encryption_key_id,
|
||||||
const std::string& video_encryption_key_id,
|
const std::string& video_encryption_key_id,
|
||||||
const AudioCodec audio_codec,
|
const AudioCodec audio_codec)
|
||||||
const scoped_refptr<MediaLog>& media_log)
|
|
||||||
: timecode_multiplier_(timecode_scale / 1000.0),
|
: timecode_multiplier_(timecode_scale / 1000.0),
|
||||||
ignored_tracks_(ignored_tracks),
|
ignored_tracks_(ignored_tracks),
|
||||||
audio_encryption_key_id_(audio_encryption_key_id),
|
audio_encryption_key_id_(audio_encryption_key_id),
|
||||||
|
@ -50,15 +65,14 @@ WebMClusterParser::WebMClusterParser(
|
||||||
audio_codec_(audio_codec),
|
audio_codec_(audio_codec),
|
||||||
parser_(kWebMIdCluster, this),
|
parser_(kWebMIdCluster, this),
|
||||||
cluster_start_time_(kNoTimestamp()),
|
cluster_start_time_(kNoTimestamp()),
|
||||||
audio_(audio_track_num, false, audio_default_duration, media_log),
|
audio_(audio_track_num, false, audio_default_duration),
|
||||||
video_(video_track_num, true, video_default_duration, media_log),
|
video_(video_track_num, true, video_default_duration),
|
||||||
ready_buffer_upper_bound_(kNoDecodeTimestamp()),
|
ready_buffer_upper_bound_(kNoDecodeTimestamp()) {
|
||||||
media_log_(media_log) {
|
|
||||||
for (WebMTracksParser::TextTracks::const_iterator it = text_tracks.begin();
|
for (WebMTracksParser::TextTracks::const_iterator it = text_tracks.begin();
|
||||||
it != text_tracks.end();
|
it != text_tracks.end();
|
||||||
++it) {
|
++it) {
|
||||||
text_track_map_.insert(std::make_pair(
|
text_track_map_.insert(
|
||||||
it->first, Track(it->first, false, kNoTimestamp(), media_log_)));
|
std::make_pair(it->first, Track(it->first, false, kNoTimestamp())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,8 +193,7 @@ base::TimeDelta WebMClusterParser::ReadOpusDuration(const uint8_t* data,
|
||||||
base::TimeDelta::FromMilliseconds(120);
|
base::TimeDelta::FromMilliseconds(120);
|
||||||
|
|
||||||
if (size < 1) {
|
if (size < 1) {
|
||||||
LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_,
|
LIMITED_DLOG(INFO, num_duration_errors_, kMaxDurationErrorLogs)
|
||||||
kMaxDurationErrorLogs)
|
|
||||||
<< "Invalid zero-byte Opus packet; demuxed block duration may be "
|
<< "Invalid zero-byte Opus packet; demuxed block duration may be "
|
||||||
"imprecise.";
|
"imprecise.";
|
||||||
return kNoTimestamp();
|
return kNoTimestamp();
|
||||||
|
@ -201,8 +214,7 @@ base::TimeDelta WebMClusterParser::ReadOpusDuration(const uint8_t* data,
|
||||||
case 3:
|
case 3:
|
||||||
// Type 3 indicates an arbitrary frame count described in the next byte.
|
// Type 3 indicates an arbitrary frame count described in the next byte.
|
||||||
if (size < 2) {
|
if (size < 2) {
|
||||||
LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_,
|
LIMITED_DLOG(INFO, num_duration_errors_, kMaxDurationErrorLogs)
|
||||||
kMaxDurationErrorLogs)
|
|
||||||
<< "Second byte missing from 'Code 3' Opus packet; demuxed block "
|
<< "Second byte missing from 'Code 3' Opus packet; demuxed block "
|
||||||
"duration may be imprecise.";
|
"duration may be imprecise.";
|
||||||
return kNoTimestamp();
|
return kNoTimestamp();
|
||||||
|
@ -211,8 +223,7 @@ base::TimeDelta WebMClusterParser::ReadOpusDuration(const uint8_t* data,
|
||||||
frame_count = data[1] & kFrameCountMask;
|
frame_count = data[1] & kFrameCountMask;
|
||||||
|
|
||||||
if (frame_count == 0) {
|
if (frame_count == 0) {
|
||||||
LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_,
|
LIMITED_DLOG(INFO, num_duration_errors_, kMaxDurationErrorLogs)
|
||||||
kMaxDurationErrorLogs)
|
|
||||||
<< "Illegal 'Code 3' Opus packet with frame count zero; demuxed "
|
<< "Illegal 'Code 3' Opus packet with frame count zero; demuxed "
|
||||||
"block duration may be imprecise.";
|
"block duration may be imprecise.";
|
||||||
return kNoTimestamp();
|
return kNoTimestamp();
|
||||||
|
@ -220,8 +231,7 @@ base::TimeDelta WebMClusterParser::ReadOpusDuration(const uint8_t* data,
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_,
|
LIMITED_DLOG(INFO, num_duration_errors_, kMaxDurationErrorLogs)
|
||||||
kMaxDurationErrorLogs)
|
|
||||||
<< "Unexpected Opus frame count type: " << frame_count_type << "; "
|
<< "Unexpected Opus frame count type: " << frame_count_type << "; "
|
||||||
<< "demuxed block duration may be imprecise.";
|
<< "demuxed block duration may be imprecise.";
|
||||||
return kNoTimestamp();
|
return kNoTimestamp();
|
||||||
|
@ -237,10 +247,9 @@ base::TimeDelta WebMClusterParser::ReadOpusDuration(const uint8_t* data,
|
||||||
|
|
||||||
if (duration > kPacketDurationMax) {
|
if (duration > kPacketDurationMax) {
|
||||||
// Intentionally allowing packet to pass through for now. Decoder should
|
// Intentionally allowing packet to pass through for now. Decoder should
|
||||||
// either handle or fail gracefully. MEDIA_LOG as breadcrumbs in case
|
// either handle or fail gracefully. LOG as breadcrumbs in case
|
||||||
// things go sideways.
|
// things go sideways.
|
||||||
LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_,
|
LIMITED_DLOG(INFO, num_duration_errors_, kMaxDurationErrorLogs)
|
||||||
kMaxDurationErrorLogs)
|
|
||||||
<< "Warning, demuxed Opus packet with encoded duration: "
|
<< "Warning, demuxed Opus packet with encoded duration: "
|
||||||
<< duration.InMilliseconds() << "ms. Should be no greater than "
|
<< duration.InMilliseconds() << "ms. Should be no greater than "
|
||||||
<< kPacketDurationMax.InMilliseconds() << "ms.";
|
<< kPacketDurationMax.InMilliseconds() << "ms.";
|
||||||
|
@ -274,7 +283,7 @@ bool WebMClusterParser::OnListEnd(int id) {
|
||||||
|
|
||||||
// Make sure the BlockGroup actually had a Block.
|
// Make sure the BlockGroup actually had a Block.
|
||||||
if (block_data_size_ == -1) {
|
if (block_data_size_ == -1) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Block missing from BlockGroup.";
|
LOG(ERROR) << "Block missing from BlockGroup.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,8 +302,8 @@ bool WebMClusterParser::OnListEnd(int id) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMClusterParser::OnUInt(int id, int64 val) {
|
bool WebMClusterParser::OnUInt(int id, int64_t val) {
|
||||||
int64* dst;
|
int64_t* dst;
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case kWebMIdTimecode:
|
case kWebMIdTimecode:
|
||||||
dst = &cluster_timecode_;
|
dst = &cluster_timecode_;
|
||||||
|
@ -320,14 +329,14 @@ bool WebMClusterParser::ParseBlock(bool is_simple_block,
|
||||||
const uint8_t* additional,
|
const uint8_t* additional,
|
||||||
int additional_size,
|
int additional_size,
|
||||||
int duration,
|
int duration,
|
||||||
int64 discard_padding) {
|
int64_t discard_padding) {
|
||||||
if (size < 4)
|
if (size < 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Return an error if the trackNum > 127. We just aren't
|
// Return an error if the trackNum > 127. We just aren't
|
||||||
// going to support large track numbers right now.
|
// going to support large track numbers right now.
|
||||||
if (!(buf[0] & 0x80)) {
|
if (!(buf[0] & 0x80)) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "TrackNumber over 127 not supported";
|
LOG(ERROR) << "TrackNumber over 127 not supported";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,8 +346,7 @@ bool WebMClusterParser::ParseBlock(bool is_simple_block,
|
||||||
int lacing = (flags >> 1) & 0x3;
|
int lacing = (flags >> 1) & 0x3;
|
||||||
|
|
||||||
if (lacing) {
|
if (lacing) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Lacing " << lacing
|
LOG(ERROR) << "Lacing " << lacing << " is not supported yet.";
|
||||||
<< " is not supported yet.";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,9 +368,8 @@ bool WebMClusterParser::OnBinary(int id, const uint8_t* data, int size) {
|
||||||
|
|
||||||
case kWebMIdBlock:
|
case kWebMIdBlock:
|
||||||
if (block_data_) {
|
if (block_data_) {
|
||||||
MEDIA_LOG(ERROR, media_log_)
|
LOG(ERROR) << "More than 1 Block in a BlockGroup is not "
|
||||||
<< "More than 1 Block in a BlockGroup is not "
|
"supported.";
|
||||||
"supported.";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
block_data_.reset(new uint8_t[size]);
|
block_data_.reset(new uint8_t[size]);
|
||||||
|
@ -371,14 +378,14 @@ bool WebMClusterParser::OnBinary(int id, const uint8_t* data, int size) {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case kWebMIdBlockAdditional: {
|
case kWebMIdBlockAdditional: {
|
||||||
uint64 block_add_id = base::HostToNet64(block_add_id_);
|
uint64_t block_add_id = base::HostToNet64(block_add_id_);
|
||||||
if (block_additional_data_) {
|
if (block_additional_data_) {
|
||||||
// TODO(vigneshv): Technically, more than 1 BlockAdditional is allowed
|
// TODO(vigneshv): Technically, more than 1 BlockAdditional is allowed
|
||||||
// as per matroska spec. But for now we don't have a use case to
|
// as per matroska spec. But for now we don't have a use case to
|
||||||
// support parsing of such files. Take a look at this again when such a
|
// support parsing of such files. Take a look at this again when such a
|
||||||
// case arises.
|
// case arises.
|
||||||
MEDIA_LOG(ERROR, media_log_) << "More than 1 BlockAdditional in a "
|
LOG(ERROR) << "More than 1 BlockAdditional in a "
|
||||||
"BlockGroup is not supported.";
|
"BlockGroup is not supported.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// First 8 bytes of side_data in DecoderBuffer is the BlockAddID
|
// First 8 bytes of side_data in DecoderBuffer is the BlockAddID
|
||||||
|
@ -397,7 +404,7 @@ bool WebMClusterParser::OnBinary(int id, const uint8_t* data, int size) {
|
||||||
discard_padding_set_ = true;
|
discard_padding_set_ = true;
|
||||||
|
|
||||||
// Read in the big-endian integer.
|
// Read in the big-endian integer.
|
||||||
discard_padding_ = static_cast<int8>(data[0]);
|
discard_padding_ = static_cast<int8_t>(data[0]);
|
||||||
for (int i = 1; i < size; ++i)
|
for (int i = 1; i < size; ++i)
|
||||||
discard_padding_ = (discard_padding_ << 8) | data[i];
|
discard_padding_ = (discard_padding_ << 8) | data[i];
|
||||||
|
|
||||||
|
@ -417,24 +424,22 @@ bool WebMClusterParser::OnBlock(bool is_simple_block,
|
||||||
int size,
|
int size,
|
||||||
const uint8_t* additional,
|
const uint8_t* additional,
|
||||||
int additional_size,
|
int additional_size,
|
||||||
int64 discard_padding) {
|
int64_t discard_padding) {
|
||||||
DCHECK_GE(size, 0);
|
DCHECK_GE(size, 0);
|
||||||
if (cluster_timecode_ == -1) {
|
if (cluster_timecode_ == -1) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Got a block before cluster timecode.";
|
LOG(ERROR) << "Got a block before cluster timecode.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(acolwell): Should relative negative timecode offsets be rejected? Or
|
// TODO(acolwell): Should relative negative timecode offsets be rejected? Or
|
||||||
// only when the absolute timecode is negative? See http://crbug.com/271794
|
// only when the absolute timecode is negative? See http://crbug.com/271794
|
||||||
if (timecode < 0) {
|
if (timecode < 0) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Got a block with negative timecode offset "
|
LOG(ERROR) << "Got a block with negative timecode offset " << timecode;
|
||||||
<< timecode;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_block_timecode_ != -1 && timecode < last_block_timecode_) {
|
if (last_block_timecode_ != -1 && timecode < last_block_timecode_) {
|
||||||
MEDIA_LOG(ERROR, media_log_)
|
LOG(ERROR) << "Got a block with a timecode before the previous block.";
|
||||||
<< "Got a block with a timecode before the previous block.";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,7 +467,7 @@ bool WebMClusterParser::OnBlock(bool is_simple_block,
|
||||||
track = text_track;
|
track = text_track;
|
||||||
buffer_type = DemuxerStream::TEXT;
|
buffer_type = DemuxerStream::TEXT;
|
||||||
} else {
|
} else {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unexpected track number " << track_num;
|
LOG(ERROR) << "Unexpected track number " << track_num;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,8 +565,7 @@ bool WebMClusterParser::OnBlock(bool is_simple_block,
|
||||||
const auto kWarnDurationDiff =
|
const auto kWarnDurationDiff =
|
||||||
base::TimeDelta::FromMicroseconds(timecode_multiplier_ * 2);
|
base::TimeDelta::FromMicroseconds(timecode_multiplier_ * 2);
|
||||||
if (duration_difference.magnitude() > kWarnDurationDiff) {
|
if (duration_difference.magnitude() > kWarnDurationDiff) {
|
||||||
LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_,
|
LIMITED_DLOG(INFO, num_duration_errors_, kMaxDurationErrorLogs)
|
||||||
kMaxDurationErrorLogs)
|
|
||||||
<< "BlockDuration (" << block_duration_time_delta.InMilliseconds()
|
<< "BlockDuration (" << block_duration_time_delta.InMilliseconds()
|
||||||
<< "ms) differs significantly from encoded duration ("
|
<< "ms) differs significantly from encoded duration ("
|
||||||
<< encoded_duration.InMilliseconds() << "ms).";
|
<< encoded_duration.InMilliseconds() << "ms).";
|
||||||
|
@ -585,13 +589,11 @@ bool WebMClusterParser::OnBlock(bool is_simple_block,
|
||||||
|
|
||||||
WebMClusterParser::Track::Track(int track_num,
|
WebMClusterParser::Track::Track(int track_num,
|
||||||
bool is_video,
|
bool is_video,
|
||||||
base::TimeDelta default_duration,
|
base::TimeDelta default_duration)
|
||||||
const scoped_refptr<MediaLog>& media_log)
|
|
||||||
: track_num_(track_num),
|
: track_num_(track_num),
|
||||||
is_video_(is_video),
|
is_video_(is_video),
|
||||||
default_duration_(default_duration),
|
default_duration_(default_duration),
|
||||||
estimated_next_frame_duration_(kNoTimestamp()),
|
estimated_next_frame_duration_(kNoTimestamp()) {
|
||||||
media_log_(media_log) {
|
|
||||||
DCHECK(default_duration_ == kNoTimestamp() ||
|
DCHECK(default_duration_ == kNoTimestamp() ||
|
||||||
default_duration_ > base::TimeDelta());
|
default_duration_ > base::TimeDelta());
|
||||||
}
|
}
|
||||||
|
@ -691,8 +693,7 @@ void WebMClusterParser::Track::ApplyDurationEstimateIfNeeded() {
|
||||||
last_added_buffer_missing_duration_->set_is_duration_estimated(true);
|
last_added_buffer_missing_duration_->set_is_duration_estimated(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
LIMITED_MEDIA_LOG(INFO, media_log_, num_duration_estimates_,
|
LIMITED_LOG(INFO, num_duration_estimates_, kMaxDurationEstimateLogs)
|
||||||
kMaxDurationEstimateLogs)
|
|
||||||
<< "Estimating WebM block duration to be "
|
<< "Estimating WebM block duration to be "
|
||||||
<< estimated_duration.InMilliseconds()
|
<< estimated_duration.InMilliseconds()
|
||||||
<< "ms for the last (Simple)Block in the Cluster for this Track. Use "
|
<< "ms for the last (Simple)Block in the Cluster for this Track. Use "
|
||||||
|
@ -751,7 +752,7 @@ bool WebMClusterParser::Track::QueueBuffer(
|
||||||
const scoped_refptr<StreamParserBuffer>& buffer) {
|
const scoped_refptr<StreamParserBuffer>& buffer) {
|
||||||
DCHECK(!last_added_buffer_missing_duration_.get());
|
DCHECK(!last_added_buffer_missing_duration_.get());
|
||||||
|
|
||||||
// WebMClusterParser::OnBlock() gives MEDIA_LOG and parse error on decreasing
|
// WebMClusterParser::OnBlock() gives LOG and parse error on decreasing
|
||||||
// block timecode detection within a cluster. Therefore, we should not see
|
// block timecode detection within a cluster. Therefore, we should not see
|
||||||
// those here.
|
// those here.
|
||||||
DecodeTimestamp previous_buffers_timestamp = buffers_.empty() ?
|
DecodeTimestamp previous_buffers_timestamp = buffers_.empty() ?
|
||||||
|
@ -760,8 +761,7 @@ bool WebMClusterParser::Track::QueueBuffer(
|
||||||
|
|
||||||
base::TimeDelta duration = buffer->duration();
|
base::TimeDelta duration = buffer->duration();
|
||||||
if (duration < base::TimeDelta() || duration == kNoTimestamp()) {
|
if (duration < base::TimeDelta() || duration == kNoTimestamp()) {
|
||||||
MEDIA_LOG(ERROR, media_log_)
|
LOG(ERROR) << "Invalid buffer duration: " << duration.InSecondsF();
|
||||||
<< "Invalid buffer duration: " << duration.InSecondsF();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -880,3 +880,4 @@ WebMClusterParser::FindTextTrack(int track_num) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -10,18 +10,17 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
#include "media/base/audio_decoder_config.h"
|
#include "packager/media/base/audio_decoder_config.h"
|
||||||
#include "media/base/media_export.h"
|
#include "packager/media/base/stream_parser.h"
|
||||||
#include "media/base/media_log.h"
|
#include "packager/media/base/stream_parser_buffer.h"
|
||||||
#include "media/base/stream_parser.h"
|
#include "packager/media/formats/webm/webm_parser.h"
|
||||||
#include "media/base/stream_parser_buffer.h"
|
#include "packager/media/formats/webm/webm_tracks_parser.h"
|
||||||
#include "media/formats/webm/webm_parser.h"
|
|
||||||
#include "media/formats/webm/webm_tracks_parser.h"
|
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
|
class WebMClusterParser : public WebMParserClient {
|
||||||
public:
|
public:
|
||||||
typedef StreamParser::TrackId TrackId;
|
typedef StreamParser::TrackId TrackId;
|
||||||
typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
|
typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
|
||||||
|
@ -50,8 +49,7 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
|
||||||
public:
|
public:
|
||||||
Track(int track_num,
|
Track(int track_num,
|
||||||
bool is_video,
|
bool is_video,
|
||||||
base::TimeDelta default_duration,
|
base::TimeDelta default_duration);
|
||||||
const scoped_refptr<MediaLog>& media_log);
|
|
||||||
~Track();
|
~Track();
|
||||||
|
|
||||||
int track_num() const { return track_num_; }
|
int track_num() const { return track_num_; }
|
||||||
|
@ -112,7 +110,7 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
|
||||||
base::TimeDelta GetDurationEstimate();
|
base::TimeDelta GetDurationEstimate();
|
||||||
|
|
||||||
// Counts the number of estimated durations used in this track. Used to
|
// Counts the number of estimated durations used in this track. Used to
|
||||||
// prevent log spam for MEDIA_LOG()s about estimated duration.
|
// prevent log spam for LOG()s about estimated duration.
|
||||||
int num_duration_estimates_ = 0;
|
int num_duration_estimates_ = 0;
|
||||||
|
|
||||||
int track_num_;
|
int track_num_;
|
||||||
|
@ -142,24 +140,21 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
|
||||||
// TODO(chcunningham): Use maximum for audio too, adding checks to disable
|
// TODO(chcunningham): Use maximum for audio too, adding checks to disable
|
||||||
// splicing when these estimates are observed in SourceBufferStream.
|
// splicing when these estimates are observed in SourceBufferStream.
|
||||||
base::TimeDelta estimated_next_frame_duration_;
|
base::TimeDelta estimated_next_frame_duration_;
|
||||||
|
|
||||||
scoped_refptr<MediaLog> media_log_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map<int, Track> TextTrackMap;
|
typedef std::map<int, Track> TextTrackMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WebMClusterParser(int64 timecode_scale,
|
WebMClusterParser(int64_t timecode_scale,
|
||||||
int audio_track_num,
|
int audio_track_num,
|
||||||
base::TimeDelta audio_default_duration,
|
base::TimeDelta audio_default_duration,
|
||||||
int video_track_num,
|
int video_track_num,
|
||||||
base::TimeDelta video_default_duration,
|
base::TimeDelta video_default_duration,
|
||||||
const WebMTracksParser::TextTracks& text_tracks,
|
const WebMTracksParser::TextTracks& text_tracks,
|
||||||
const std::set<int64>& ignored_tracks,
|
const std::set<int64_t>& ignored_tracks,
|
||||||
const std::string& audio_encryption_key_id,
|
const std::string& audio_encryption_key_id,
|
||||||
const std::string& video_encryption_key_id,
|
const std::string& video_encryption_key_id,
|
||||||
const AudioCodec audio_codec,
|
const AudioCodec audio_codec);
|
||||||
const scoped_refptr<MediaLog>& media_log);
|
|
||||||
~WebMClusterParser() override;
|
~WebMClusterParser() override;
|
||||||
|
|
||||||
// Resets the parser state so it can accept a new cluster.
|
// Resets the parser state so it can accept a new cluster.
|
||||||
|
@ -209,7 +204,7 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
|
||||||
// WebMParserClient methods.
|
// WebMParserClient methods.
|
||||||
WebMParserClient* OnListStart(int id) override;
|
WebMParserClient* OnListStart(int id) override;
|
||||||
bool OnListEnd(int id) override;
|
bool OnListEnd(int id) override;
|
||||||
bool OnUInt(int id, int64 val) override;
|
bool OnUInt(int id, int64_t val) override;
|
||||||
bool OnBinary(int id, const uint8_t* data, int size) override;
|
bool OnBinary(int id, const uint8_t* data, int size) override;
|
||||||
|
|
||||||
bool ParseBlock(bool is_simple_block,
|
bool ParseBlock(bool is_simple_block,
|
||||||
|
@ -218,7 +213,7 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
|
||||||
const uint8_t* additional,
|
const uint8_t* additional,
|
||||||
int additional_size,
|
int additional_size,
|
||||||
int duration,
|
int duration,
|
||||||
int64 discard_padding);
|
int64_t discard_padding);
|
||||||
bool OnBlock(bool is_simple_block,
|
bool OnBlock(bool is_simple_block,
|
||||||
int track_num,
|
int track_num,
|
||||||
int timecode,
|
int timecode,
|
||||||
|
@ -228,7 +223,7 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
|
||||||
int size,
|
int size,
|
||||||
const uint8_t* additional,
|
const uint8_t* additional,
|
||||||
int additional_size,
|
int additional_size,
|
||||||
int64 discard_padding);
|
int64_t discard_padding);
|
||||||
|
|
||||||
// Resets the Track objects associated with each text track.
|
// Resets the Track objects associated with each text track.
|
||||||
void ResetTextTracks();
|
void ResetTextTracks();
|
||||||
|
@ -267,34 +262,34 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
|
||||||
// as TimeDelta or kNoTimestamp() upon failure to read duration from packet.
|
// as TimeDelta or kNoTimestamp() upon failure to read duration from packet.
|
||||||
base::TimeDelta ReadOpusDuration(const uint8_t* data, int size);
|
base::TimeDelta ReadOpusDuration(const uint8_t* data, int size);
|
||||||
|
|
||||||
// Tracks the number of MEDIA_LOGs made in process of reading encoded
|
// Tracks the number of LOGs made in process of reading encoded
|
||||||
// duration. Useful to prevent log spam.
|
// duration. Useful to prevent log spam.
|
||||||
int num_duration_errors_ = 0;
|
int num_duration_errors_ = 0;
|
||||||
|
|
||||||
double timecode_multiplier_; // Multiplier used to convert timecodes into
|
double timecode_multiplier_; // Multiplier used to convert timecodes into
|
||||||
// microseconds.
|
// microseconds.
|
||||||
std::set<int64> ignored_tracks_;
|
std::set<int64_t> ignored_tracks_;
|
||||||
std::string audio_encryption_key_id_;
|
std::string audio_encryption_key_id_;
|
||||||
std::string video_encryption_key_id_;
|
std::string video_encryption_key_id_;
|
||||||
const AudioCodec audio_codec_;
|
const AudioCodec audio_codec_;
|
||||||
|
|
||||||
WebMListParser parser_;
|
WebMListParser parser_;
|
||||||
|
|
||||||
int64 last_block_timecode_ = -1;
|
int64_t last_block_timecode_ = -1;
|
||||||
scoped_ptr<uint8_t[]> block_data_;
|
scoped_ptr<uint8_t[]> block_data_;
|
||||||
int block_data_size_ = -1;
|
int block_data_size_ = -1;
|
||||||
int64 block_duration_ = -1;
|
int64_t block_duration_ = -1;
|
||||||
int64 block_add_id_ = -1;
|
int64_t block_add_id_ = -1;
|
||||||
|
|
||||||
scoped_ptr<uint8_t[]> block_additional_data_;
|
scoped_ptr<uint8_t[]> block_additional_data_;
|
||||||
// Must be 0 if |block_additional_data_| is null. Must be > 0 if
|
// Must be 0 if |block_additional_data_| is null. Must be > 0 if
|
||||||
// |block_additional_data_| is NOT null.
|
// |block_additional_data_| is NOT null.
|
||||||
int block_additional_data_size_ = 0;
|
int block_additional_data_size_ = 0;
|
||||||
|
|
||||||
int64 discard_padding_ = -1;
|
int64_t discard_padding_ = -1;
|
||||||
bool discard_padding_set_ = false;
|
bool discard_padding_set_ = false;
|
||||||
|
|
||||||
int64 cluster_timecode_ = -1;
|
int64_t cluster_timecode_ = -1;
|
||||||
base::TimeDelta cluster_start_time_;
|
base::TimeDelta cluster_start_time_;
|
||||||
bool cluster_ended_ = false;
|
bool cluster_ended_ = false;
|
||||||
|
|
||||||
|
@ -315,11 +310,10 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
|
||||||
// kInfiniteDuration() if no buffers are currently missing duration.
|
// kInfiniteDuration() if no buffers are currently missing duration.
|
||||||
DecodeTimestamp ready_buffer_upper_bound_;
|
DecodeTimestamp ready_buffer_upper_bound_;
|
||||||
|
|
||||||
scoped_refptr<MediaLog> media_log_;
|
|
||||||
|
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(WebMClusterParser);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(WebMClusterParser);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_WEBM_CLUSTER_PARSER_H_
|
#endif // MEDIA_FORMATS_WEBM_WEBM_CLUSTER_PARSER_H_
|
||||||
|
|
|
@ -2,24 +2,25 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "packager/media/formats/webm/webm_cluster_parser.h"
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/bind.h"
|
#include "packager/base/bind.h"
|
||||||
#include "base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "base/strings/string_number_conversions.h"
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
#include "media/base/audio_decoder_config.h"
|
#include "packager/media/base/audio_decoder_config.h"
|
||||||
#include "media/base/decrypt_config.h"
|
#include "packager/media/base/decrypt_config.h"
|
||||||
#include "media/base/mock_media_log.h"
|
#include "packager/media/base/timestamp_constants.h"
|
||||||
#include "media/base/timestamp_constants.h"
|
#include "packager/media/formats/webm/cluster_builder.h"
|
||||||
#include "media/formats/webm/cluster_builder.h"
|
#include "packager/media/formats/webm/opus_packet_builder.h"
|
||||||
#include "media/formats/webm/opus_packet_builder.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
#include "media/formats/webm/webm_cluster_parser.h"
|
|
||||||
#include "media/formats/webm/webm_constants.h"
|
|
||||||
#include "testing/gmock/include/gmock/gmock.h"
|
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
|
||||||
|
|
||||||
using ::testing::HasSubstr;
|
using ::testing::HasSubstr;
|
||||||
using ::testing::InSequence;
|
using ::testing::InSequence;
|
||||||
|
@ -28,6 +29,7 @@ using ::testing::StrictMock;
|
||||||
using ::testing::Mock;
|
using ::testing::Mock;
|
||||||
using ::testing::_;
|
using ::testing::_;
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
typedef WebMTracksParser::TextTracks TextTracks;
|
typedef WebMTracksParser::TextTracks TextTracks;
|
||||||
|
@ -295,9 +297,7 @@ void AppendToEnd(const WebMClusterParser::BufferQueue& src,
|
||||||
|
|
||||||
class WebMClusterParserTest : public testing::Test {
|
class WebMClusterParserTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
WebMClusterParserTest()
|
WebMClusterParserTest() : parser_(CreateDefaultParser()) {}
|
||||||
: media_log_(new StrictMock<MockMediaLog>()),
|
|
||||||
parser_(CreateDefaultParser()) {}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ResetParserToHaveDefaultDurations() {
|
void ResetParserToHaveDefaultDurations() {
|
||||||
|
@ -319,21 +319,20 @@ class WebMClusterParserTest : public testing::Test {
|
||||||
base::TimeDelta audio_default_duration,
|
base::TimeDelta audio_default_duration,
|
||||||
base::TimeDelta video_default_duration,
|
base::TimeDelta video_default_duration,
|
||||||
const WebMTracksParser::TextTracks& text_tracks,
|
const WebMTracksParser::TextTracks& text_tracks,
|
||||||
const std::set<int64>& ignored_tracks,
|
const std::set<int64_t>& ignored_tracks,
|
||||||
const std::string& audio_encryption_key_id,
|
const std::string& audio_encryption_key_id,
|
||||||
const std::string& video_encryption_key_id,
|
const std::string& video_encryption_key_id,
|
||||||
const AudioCodec audio_codec) {
|
const AudioCodec audio_codec) {
|
||||||
return new WebMClusterParser(
|
return new WebMClusterParser(
|
||||||
kTimecodeScale, kAudioTrackNum, audio_default_duration, kVideoTrackNum,
|
kTimecodeScale, kAudioTrackNum, audio_default_duration, kVideoTrackNum,
|
||||||
video_default_duration, text_tracks, ignored_tracks,
|
video_default_duration, text_tracks, ignored_tracks,
|
||||||
audio_encryption_key_id, video_encryption_key_id, audio_codec,
|
audio_encryption_key_id, video_encryption_key_id, audio_codec);
|
||||||
media_log_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a default version of the parser for test.
|
// Create a default version of the parser for test.
|
||||||
WebMClusterParser* CreateDefaultParser() {
|
WebMClusterParser* CreateDefaultParser() {
|
||||||
return CreateParserHelper(kNoTimestamp(), kNoTimestamp(), TextTracks(),
|
return CreateParserHelper(kNoTimestamp(), kNoTimestamp(), TextTracks(),
|
||||||
std::set<int64>(), std::string(), std::string(),
|
std::set<int64_t>(), std::string(), std::string(),
|
||||||
kUnknownAudioCodec);
|
kUnknownAudioCodec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,13 +343,13 @@ class WebMClusterParserTest : public testing::Test {
|
||||||
base::TimeDelta video_default_duration,
|
base::TimeDelta video_default_duration,
|
||||||
const WebMTracksParser::TextTracks& text_tracks = TextTracks()) {
|
const WebMTracksParser::TextTracks& text_tracks = TextTracks()) {
|
||||||
return CreateParserHelper(audio_default_duration, video_default_duration,
|
return CreateParserHelper(audio_default_duration, video_default_duration,
|
||||||
text_tracks, std::set<int64>(), std::string(),
|
text_tracks, std::set<int64_t>(), std::string(),
|
||||||
std::string(), kUnknownAudioCodec);
|
std::string(), kUnknownAudioCodec);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a parser for test with custom ignored tracks.
|
// Create a parser for test with custom ignored tracks.
|
||||||
WebMClusterParser* CreateParserWithIgnoredTracks(
|
WebMClusterParser* CreateParserWithIgnoredTracks(
|
||||||
std::set<int64>& ignored_tracks) {
|
std::set<int64_t>& ignored_tracks) {
|
||||||
return CreateParserHelper(kNoTimestamp(), kNoTimestamp(), TextTracks(),
|
return CreateParserHelper(kNoTimestamp(), kNoTimestamp(), TextTracks(),
|
||||||
ignored_tracks, std::string(), std::string(),
|
ignored_tracks, std::string(), std::string(),
|
||||||
kUnknownAudioCodec);
|
kUnknownAudioCodec);
|
||||||
|
@ -362,11 +361,10 @@ class WebMClusterParserTest : public testing::Test {
|
||||||
const std::string& video_encryption_key_id,
|
const std::string& video_encryption_key_id,
|
||||||
const AudioCodec audio_codec) {
|
const AudioCodec audio_codec) {
|
||||||
return CreateParserHelper(kNoTimestamp(), kNoTimestamp(), TextTracks(),
|
return CreateParserHelper(kNoTimestamp(), kNoTimestamp(), TextTracks(),
|
||||||
std::set<int64>(), audio_encryption_key_id,
|
std::set<int64_t>(), audio_encryption_key_id,
|
||||||
video_encryption_key_id, audio_codec);
|
video_encryption_key_id, audio_codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
scoped_refptr<StrictMock<MockMediaLog>> media_log_;
|
|
||||||
scoped_ptr<WebMClusterParser> parser_;
|
scoped_ptr<WebMClusterParser> parser_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -440,11 +438,6 @@ TEST_F(WebMClusterParserTest, HeldBackBufferHoldsBackAllTracks) {
|
||||||
// Parse all but the last byte unless we need to parse the full cluster.
|
// Parse all but the last byte unless we need to parse the full cluster.
|
||||||
bool parse_full_cluster = i == (block_count - 1);
|
bool parse_full_cluster = i == (block_count - 1);
|
||||||
|
|
||||||
if (parse_full_cluster) {
|
|
||||||
EXPECT_MEDIA_LOG(
|
|
||||||
WebMSimpleBlockDurationEstimated(kExpectedVideoEstimationInMs));
|
|
||||||
}
|
|
||||||
|
|
||||||
int result = parser_->Parse(cluster->data(), parse_full_cluster ?
|
int result = parser_->Parse(cluster->data(), parse_full_cluster ?
|
||||||
cluster->size() : cluster->size() - 1);
|
cluster->size() : cluster->size() - 1);
|
||||||
if (parse_full_cluster) {
|
if (parse_full_cluster) {
|
||||||
|
@ -579,7 +572,7 @@ TEST_F(WebMClusterParserTest, ParseSimpleBlockAndBlockGroupMixture) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMClusterParserTest, IgnoredTracks) {
|
TEST_F(WebMClusterParserTest, IgnoredTracks) {
|
||||||
std::set<int64> ignored_tracks;
|
std::set<int64_t> ignored_tracks;
|
||||||
ignored_tracks.insert(kTextTrackNum);
|
ignored_tracks.insert(kTextTrackNum);
|
||||||
|
|
||||||
parser_.reset(CreateParserWithIgnoredTracks(ignored_tracks));
|
parser_.reset(CreateParserWithIgnoredTracks(ignored_tracks));
|
||||||
|
@ -606,8 +599,6 @@ TEST_F(WebMClusterParserTest, IgnoredTracks) {
|
||||||
scoped_ptr<Cluster> cluster(
|
scoped_ptr<Cluster> cluster(
|
||||||
CreateCluster(0, kInputBlockInfo, input_block_count));
|
CreateCluster(0, kInputBlockInfo, input_block_count));
|
||||||
|
|
||||||
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(23));
|
|
||||||
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(34));
|
|
||||||
int result = parser_->Parse(cluster->data(), cluster->size());
|
int result = parser_->Parse(cluster->data(), cluster->size());
|
||||||
EXPECT_EQ(cluster->size(), result);
|
EXPECT_EQ(cluster->size(), result);
|
||||||
ASSERT_TRUE(VerifyBuffers(parser_, kOutputBlockInfo, output_block_count));
|
ASSERT_TRUE(VerifyBuffers(parser_, kOutputBlockInfo, output_block_count));
|
||||||
|
@ -637,8 +628,6 @@ TEST_F(WebMClusterParserTest, ParseTextTracks) {
|
||||||
scoped_ptr<Cluster> cluster(
|
scoped_ptr<Cluster> cluster(
|
||||||
CreateCluster(0, kInputBlockInfo, input_block_count));
|
CreateCluster(0, kInputBlockInfo, input_block_count));
|
||||||
|
|
||||||
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(23));
|
|
||||||
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(34));
|
|
||||||
int result = parser_->Parse(cluster->data(), cluster->size());
|
int result = parser_->Parse(cluster->data(), cluster->size());
|
||||||
EXPECT_EQ(cluster->size(), result);
|
EXPECT_EQ(cluster->size(), result);
|
||||||
ASSERT_TRUE(VerifyBuffers(parser_, kInputBlockInfo, input_block_count));
|
ASSERT_TRUE(VerifyBuffers(parser_, kInputBlockInfo, input_block_count));
|
||||||
|
@ -698,8 +687,6 @@ TEST_F(WebMClusterParserTest, ParseMultipleTextTracks) {
|
||||||
scoped_ptr<Cluster> cluster(
|
scoped_ptr<Cluster> cluster(
|
||||||
CreateCluster(0, kInputBlockInfo, input_block_count));
|
CreateCluster(0, kInputBlockInfo, input_block_count));
|
||||||
|
|
||||||
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(23));
|
|
||||||
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(34));
|
|
||||||
int result = parser_->Parse(cluster->data(), cluster->size());
|
int result = parser_->Parse(cluster->data(), cluster->size());
|
||||||
EXPECT_EQ(cluster->size(), result);
|
EXPECT_EQ(cluster->size(), result);
|
||||||
|
|
||||||
|
@ -723,10 +710,6 @@ TEST_F(WebMClusterParserTest, ParseEncryptedBlock) {
|
||||||
parser_.reset(CreateParserWithKeyIdsAndAudioCodec(
|
parser_.reset(CreateParserWithKeyIdsAndAudioCodec(
|
||||||
std::string(), "video_key_id", kUnknownAudioCodec));
|
std::string(), "video_key_id", kUnknownAudioCodec));
|
||||||
|
|
||||||
// The encrypted cluster contains just one block, video.
|
|
||||||
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(
|
|
||||||
WebMClusterParser::kDefaultVideoBufferDurationInMs));
|
|
||||||
|
|
||||||
int result = parser_->Parse(cluster->data(), cluster->size());
|
int result = parser_->Parse(cluster->data(), cluster->size());
|
||||||
EXPECT_EQ(cluster->size(), result);
|
EXPECT_EQ(cluster->size(), result);
|
||||||
ASSERT_EQ(1UL, parser_->GetVideoBuffers().size());
|
ASSERT_EQ(1UL, parser_->GetVideoBuffers().size());
|
||||||
|
@ -858,10 +841,6 @@ TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsSimpleBlocks) {
|
||||||
parser_->Reset();
|
parser_->Reset();
|
||||||
|
|
||||||
// Now parse the full first cluster and verify all the blocks are parsed.
|
// Now parse the full first cluster and verify all the blocks are parsed.
|
||||||
EXPECT_MEDIA_LOG(
|
|
||||||
WebMSimpleBlockDurationEstimated(kExpectedAudioEstimationInMs));
|
|
||||||
EXPECT_MEDIA_LOG(
|
|
||||||
WebMSimpleBlockDurationEstimated(kExpectedVideoEstimationInMs));
|
|
||||||
result = parser_->Parse(cluster1->data(), cluster1->size());
|
result = parser_->Parse(cluster1->data(), cluster1->size());
|
||||||
EXPECT_EQ(cluster1->size(), result);
|
EXPECT_EQ(cluster1->size(), result);
|
||||||
ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1));
|
ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1));
|
||||||
|
@ -877,10 +856,6 @@ TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsSimpleBlocks) {
|
||||||
|
|
||||||
int block_count2 = arraysize(kBlockInfo2);
|
int block_count2 = arraysize(kBlockInfo2);
|
||||||
scoped_ptr<Cluster> cluster2(CreateCluster(0, kBlockInfo2, block_count2));
|
scoped_ptr<Cluster> cluster2(CreateCluster(0, kBlockInfo2, block_count2));
|
||||||
EXPECT_MEDIA_LOG(
|
|
||||||
WebMSimpleBlockDurationEstimated(kExpectedAudioEstimationInMs));
|
|
||||||
EXPECT_MEDIA_LOG(
|
|
||||||
WebMSimpleBlockDurationEstimated(kExpectedVideoEstimationInMs));
|
|
||||||
result = parser_->Parse(cluster2->data(), cluster2->size());
|
result = parser_->Parse(cluster2->data(), cluster2->size());
|
||||||
EXPECT_EQ(cluster2->size(), result);
|
EXPECT_EQ(cluster2->size(), result);
|
||||||
ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo2, block_count2));
|
ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo2, block_count2));
|
||||||
|
@ -926,10 +901,6 @@ TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsBlockGroups) {
|
||||||
parser_->Reset();
|
parser_->Reset();
|
||||||
|
|
||||||
// Now parse the full first cluster and verify all the blocks are parsed.
|
// Now parse the full first cluster and verify all the blocks are parsed.
|
||||||
EXPECT_MEDIA_LOG(
|
|
||||||
WebMSimpleBlockDurationEstimated(kExpectedAudioEstimationInMs));
|
|
||||||
EXPECT_MEDIA_LOG(
|
|
||||||
WebMSimpleBlockDurationEstimated(kExpectedVideoEstimationInMs));
|
|
||||||
result = parser_->Parse(cluster1->data(), cluster1->size());
|
result = parser_->Parse(cluster1->data(), cluster1->size());
|
||||||
EXPECT_EQ(cluster1->size(), result);
|
EXPECT_EQ(cluster1->size(), result);
|
||||||
ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1));
|
ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1));
|
||||||
|
@ -943,10 +914,6 @@ TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsBlockGroups) {
|
||||||
|
|
||||||
int block_count2 = arraysize(kBlockInfo2);
|
int block_count2 = arraysize(kBlockInfo2);
|
||||||
scoped_ptr<Cluster> cluster2(CreateCluster(0, kBlockInfo2, block_count2));
|
scoped_ptr<Cluster> cluster2(CreateCluster(0, kBlockInfo2, block_count2));
|
||||||
EXPECT_MEDIA_LOG(
|
|
||||||
WebMSimpleBlockDurationEstimated(kExpectedAudioEstimationInMs));
|
|
||||||
EXPECT_MEDIA_LOG(
|
|
||||||
WebMSimpleBlockDurationEstimated(kExpectedVideoEstimationInMs));
|
|
||||||
result = parser_->Parse(cluster2->data(), cluster2->size());
|
result = parser_->Parse(cluster2->data(), cluster2->size());
|
||||||
EXPECT_EQ(cluster2->size(), result);
|
EXPECT_EQ(cluster2->size(), result);
|
||||||
ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo2, block_count2));
|
ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo2, block_count2));
|
||||||
|
@ -1013,10 +980,6 @@ TEST_F(WebMClusterParserTest,
|
||||||
|
|
||||||
int block_count = arraysize(kBlockInfo);
|
int block_count = arraysize(kBlockInfo);
|
||||||
scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
|
scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
|
||||||
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(
|
|
||||||
WebMClusterParser::kDefaultAudioBufferDurationInMs));
|
|
||||||
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(
|
|
||||||
WebMClusterParser::kDefaultVideoBufferDurationInMs));
|
|
||||||
int result = parser_->Parse(cluster->data(), cluster->size());
|
int result = parser_->Parse(cluster->data(), cluster->size());
|
||||||
EXPECT_EQ(cluster->size(), result);
|
EXPECT_EQ(cluster->size(), result);
|
||||||
ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
|
ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
|
||||||
|
@ -1043,7 +1006,7 @@ TEST_F(WebMClusterParserTest, ReadOpusDurationsSimpleBlockAtEndOfCluster) {
|
||||||
for (const auto* packet_ptr : BuildAllOpusPackets()) {
|
for (const auto* packet_ptr : BuildAllOpusPackets()) {
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
// Get a new parser each iteration to prevent exceeding the media log cap.
|
// Get a new parser each iteration to prevent exceeding the log cap.
|
||||||
parser_.reset(CreateParserWithKeyIdsAndAudioCodec(
|
parser_.reset(CreateParserWithKeyIdsAndAudioCodec(
|
||||||
std::string(), std::string(), kCodecOpus));
|
std::string(), std::string(), kCodecOpus));
|
||||||
|
|
||||||
|
@ -1056,18 +1019,11 @@ TEST_F(WebMClusterParserTest, ReadOpusDurationsSimpleBlockAtEndOfCluster) {
|
||||||
|
|
||||||
int block_count = arraysize(kBlockInfo);
|
int block_count = arraysize(kBlockInfo);
|
||||||
scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
|
scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
|
||||||
int duration_ms = packet_ptr->duration_ms(); // Casts from double.
|
|
||||||
if (duration_ms > 120) {
|
|
||||||
EXPECT_MEDIA_LOG(OpusPacketDurationTooHigh(duration_ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
int result = parser_->Parse(cluster->data(), cluster->size());
|
int result = parser_->Parse(cluster->data(), cluster->size());
|
||||||
EXPECT_EQ(cluster->size(), result);
|
EXPECT_EQ(cluster->size(), result);
|
||||||
ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
|
ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
|
||||||
|
|
||||||
// Fail early if any iteration fails to meet the logging expectations.
|
|
||||||
ASSERT_TRUE(Mock::VerifyAndClearExpectations(media_log_.get()));
|
|
||||||
|
|
||||||
loop_count++;
|
loop_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1080,19 +1036,10 @@ TEST_F(WebMClusterParserTest, PreferOpusDurationsOverBlockDurations) {
|
||||||
for (const auto* packet_ptr : BuildAllOpusPackets()) {
|
for (const auto* packet_ptr : BuildAllOpusPackets()) {
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
// Get a new parser each iteration to prevent exceeding the media log cap.
|
// Get a new parser each iteration to prevent exceeding the log cap.
|
||||||
parser_.reset(CreateParserWithKeyIdsAndAudioCodec(
|
parser_.reset(CreateParserWithKeyIdsAndAudioCodec(
|
||||||
std::string(), std::string(), kCodecOpus));
|
std::string(), std::string(), kCodecOpus));
|
||||||
|
|
||||||
// Setting BlockDuration != Opus duration to see which one the parser uses.
|
|
||||||
int block_duration_ms = packet_ptr->duration_ms() + 10;
|
|
||||||
if (packet_ptr->duration_ms() > 120) {
|
|
||||||
EXPECT_MEDIA_LOG(OpusPacketDurationTooHigh(packet_ptr->duration_ms()));
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPECT_MEDIA_LOG(WebMBlockDurationMismatchesOpusDuration(
|
|
||||||
block_duration_ms, packet_ptr->duration_ms()));
|
|
||||||
|
|
||||||
BlockInfo block_infos[] = {{kAudioTrackNum,
|
BlockInfo block_infos[] = {{kAudioTrackNum,
|
||||||
0,
|
0,
|
||||||
block_duration_ms,
|
block_duration_ms,
|
||||||
|
@ -1111,9 +1058,6 @@ TEST_F(WebMClusterParserTest, PreferOpusDurationsOverBlockDurations) {
|
||||||
|
|
||||||
ASSERT_TRUE(VerifyBuffers(parser_, block_infos, block_count));
|
ASSERT_TRUE(VerifyBuffers(parser_, block_infos, block_count));
|
||||||
|
|
||||||
// Fail early if any iteration fails to meet the logging expectations.
|
|
||||||
ASSERT_TRUE(Mock::VerifyAndClearExpectations(media_log_.get()));
|
|
||||||
|
|
||||||
loop_count++;
|
loop_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1150,3 +1094,4 @@ TEST_F(WebMClusterParserTest, DontReadEncodedDurationWhenEncrypted) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
const char kWebMCodecSubtitles[] = "D_WEBVTT/SUBTITLES";
|
const char kWebMCodecSubtitles[] = "D_WEBVTT/SUBTITLES";
|
||||||
|
@ -12,3 +13,4 @@ const char kWebMCodecDescriptions[] = "D_WEBVTT/DESCRIPTIONS";
|
||||||
const char kWebMCodecMetadata[] = "D_WEBVTT/METADATA";
|
const char kWebMCodecMetadata[] = "D_WEBVTT/METADATA";
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
#ifndef MEDIA_FORMATS_WEBM_WEBM_CONSTANTS_H_
|
#ifndef MEDIA_FORMATS_WEBM_WEBM_CONSTANTS_H_
|
||||||
#define MEDIA_FORMATS_WEBM_WEBM_CONSTANTS_H_
|
#define MEDIA_FORMATS_WEBM_WEBM_CONSTANTS_H_
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include <stdint.h>
|
||||||
#include "media/base/media_export.h"
|
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
// WebM element IDs.
|
// WebM element IDs.
|
||||||
|
@ -200,14 +200,14 @@ const int kWebMIdVideo = 0xE0;
|
||||||
const int kWebMIdVoid = 0xEC;
|
const int kWebMIdVoid = 0xEC;
|
||||||
const int kWebMIdWritingApp = 0x5741;
|
const int kWebMIdWritingApp = 0x5741;
|
||||||
|
|
||||||
const int64 kWebMReservedId = 0x1FFFFFFF;
|
const int64_t kWebMReservedId = 0x1FFFFFFF;
|
||||||
const int64 kWebMUnknownSize = 0x00FFFFFFFFFFFFFFLL;
|
const int64_t kWebMUnknownSize = 0x00FFFFFFFFFFFFFFLL;
|
||||||
|
|
||||||
const uint8 kWebMFlagKeyframe = 0x80;
|
const uint8_t kWebMFlagKeyframe = 0x80;
|
||||||
|
|
||||||
// Current encrypted WebM request for comments specification is here
|
// Current encrypted WebM request for comments specification is here
|
||||||
// http://wiki.webmproject.org/encryption/webm-encryption-rfc
|
// http://wiki.webmproject.org/encryption/webm-encryption-rfc
|
||||||
const uint8 kWebMFlagEncryptedFrame = 0x1;
|
const uint8_t kWebMFlagEncryptedFrame = 0x1;
|
||||||
const int kWebMIvSize = 8;
|
const int kWebMIvSize = 8;
|
||||||
const int kWebMSignalByteSize = 1;
|
const int kWebMSignalByteSize = 1;
|
||||||
|
|
||||||
|
@ -219,11 +219,12 @@ const int kWebMTrackTypeAudio = 2;
|
||||||
const int kWebMTrackTypeSubtitlesOrCaptions = 0x11;
|
const int kWebMTrackTypeSubtitlesOrCaptions = 0x11;
|
||||||
const int kWebMTrackTypeDescriptionsOrMetadata = 0x21;
|
const int kWebMTrackTypeDescriptionsOrMetadata = 0x21;
|
||||||
|
|
||||||
MEDIA_EXPORT extern const char kWebMCodecSubtitles[];
|
extern const char kWebMCodecSubtitles[];
|
||||||
MEDIA_EXPORT extern const char kWebMCodecCaptions[];
|
extern const char kWebMCodecCaptions[];
|
||||||
MEDIA_EXPORT extern const char kWebMCodecDescriptions[];
|
extern const char kWebMCodecDescriptions[];
|
||||||
MEDIA_EXPORT extern const char kWebMCodecMetadata[];
|
extern const char kWebMCodecMetadata[];
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_WEBM_CONSTANTS_H_
|
#endif // MEDIA_FORMATS_WEBM_WEBM_CONSTANTS_H_
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "media/formats/webm/webm_content_encodings.h"
|
#include "packager/media/formats/webm/webm_content_encodings.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
ContentEncoding::ContentEncoding()
|
ContentEncoding::ContentEncoding()
|
||||||
|
@ -17,7 +18,7 @@ ContentEncoding::ContentEncoding()
|
||||||
|
|
||||||
ContentEncoding::~ContentEncoding() {}
|
ContentEncoding::~ContentEncoding() {}
|
||||||
|
|
||||||
void ContentEncoding::SetEncryptionKeyId(const uint8* encryption_key_id,
|
void ContentEncoding::SetEncryptionKeyId(const uint8_t* encryption_key_id,
|
||||||
int size) {
|
int size) {
|
||||||
DCHECK(encryption_key_id);
|
DCHECK(encryption_key_id);
|
||||||
DCHECK_GT(size, 0);
|
DCHECK_GT(size, 0);
|
||||||
|
@ -26,3 +27,4 @@ void ContentEncoding::SetEncryptionKeyId(const uint8* encryption_key_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -5,15 +5,15 @@
|
||||||
#ifndef MEDIA_FORMATS_WEBM_WEBM_CONTENT_ENCODINGS_H_
|
#ifndef MEDIA_FORMATS_WEBM_WEBM_CONTENT_ENCODINGS_H_
|
||||||
#define MEDIA_FORMATS_WEBM_WEBM_CONTENT_ENCODINGS_H_
|
#define MEDIA_FORMATS_WEBM_WEBM_CONTENT_ENCODINGS_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
#include "base/memory/scoped_ptr.h"
|
|
||||||
#include "media/base/media_export.h"
|
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
class MEDIA_EXPORT ContentEncoding {
|
class ContentEncoding {
|
||||||
public:
|
public:
|
||||||
// The following enum definitions are based on the ContentEncoding element
|
// The following enum definitions are based on the ContentEncoding element
|
||||||
// specified in the Matroska spec.
|
// specified in the Matroska spec.
|
||||||
|
@ -52,8 +52,8 @@ class MEDIA_EXPORT ContentEncoding {
|
||||||
ContentEncoding();
|
ContentEncoding();
|
||||||
~ContentEncoding();
|
~ContentEncoding();
|
||||||
|
|
||||||
int64 order() const { return order_; }
|
int64_t order() const { return order_; }
|
||||||
void set_order(int64 order) { order_ = order; }
|
void set_order(int64_t order) { order_ = order; }
|
||||||
|
|
||||||
Scope scope() const { return scope_; }
|
Scope scope() const { return scope_; }
|
||||||
void set_scope(Scope scope) { scope_ = scope; }
|
void set_scope(Scope scope) { scope_ = scope; }
|
||||||
|
@ -67,13 +67,13 @@ class MEDIA_EXPORT ContentEncoding {
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& encryption_key_id() const { return encryption_key_id_; }
|
const std::string& encryption_key_id() const { return encryption_key_id_; }
|
||||||
void SetEncryptionKeyId(const uint8* encryption_key_id, int size);
|
void SetEncryptionKeyId(const uint8_t* encryption_key_id, int size);
|
||||||
|
|
||||||
CipherMode cipher_mode() const { return cipher_mode_; }
|
CipherMode cipher_mode() const { return cipher_mode_; }
|
||||||
void set_cipher_mode(CipherMode mode) { cipher_mode_ = mode; }
|
void set_cipher_mode(CipherMode mode) { cipher_mode_ = mode; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int64 order_;
|
int64_t order_;
|
||||||
Scope scope_;
|
Scope scope_;
|
||||||
Type type_;
|
Type type_;
|
||||||
EncryptionAlgo encryption_algo_;
|
EncryptionAlgo encryption_algo_;
|
||||||
|
@ -84,5 +84,6 @@ class MEDIA_EXPORT ContentEncoding {
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_WEBM_CONTENT_ENCODINGS_H_
|
#endif // MEDIA_FORMATS_WEBM_WEBM_CONTENT_ENCODINGS_H_
|
||||||
|
|
|
@ -2,20 +2,17 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/webm_content_encodings_client.h"
|
#include "packager/media/formats/webm/webm_content_encodings_client.h"
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "base/stl_util.h"
|
#include "packager/base/stl_util.h"
|
||||||
#include "media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
WebMContentEncodingsClient::WebMContentEncodingsClient(
|
WebMContentEncodingsClient::WebMContentEncodingsClient()
|
||||||
const scoped_refptr<MediaLog>& media_log)
|
: content_encryption_encountered_(false), content_encodings_ready_(false) {}
|
||||||
: media_log_(media_log),
|
|
||||||
content_encryption_encountered_(false),
|
|
||||||
content_encodings_ready_(false) {
|
|
||||||
}
|
|
||||||
|
|
||||||
WebMContentEncodingsClient::~WebMContentEncodingsClient() {
|
WebMContentEncodingsClient::~WebMContentEncodingsClient() {
|
||||||
STLDeleteElements(&content_encodings_);
|
STLDeleteElements(&content_encodings_);
|
||||||
|
@ -45,7 +42,7 @@ WebMParserClient* WebMContentEncodingsClient::OnListStart(int id) {
|
||||||
if (id == kWebMIdContentEncryption) {
|
if (id == kWebMIdContentEncryption) {
|
||||||
DCHECK(cur_content_encoding_.get());
|
DCHECK(cur_content_encoding_.get());
|
||||||
if (content_encryption_encountered_) {
|
if (content_encryption_encountered_) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unexpected multiple ContentEncryption.";
|
LOG(ERROR) << "Unexpected multiple ContentEncryption.";
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
content_encryption_encountered_ = true;
|
content_encryption_encountered_ = true;
|
||||||
|
@ -68,7 +65,7 @@ bool WebMContentEncodingsClient::OnListEnd(int id) {
|
||||||
if (id == kWebMIdContentEncodings) {
|
if (id == kWebMIdContentEncodings) {
|
||||||
// ContentEncoding element is mandatory. Check this!
|
// ContentEncoding element is mandatory. Check this!
|
||||||
if (content_encodings_.empty()) {
|
if (content_encodings_.empty()) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Missing ContentEncoding.";
|
LOG(ERROR) << "Missing ContentEncoding.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
content_encodings_ready_ = true;
|
content_encodings_ready_ = true;
|
||||||
|
@ -86,7 +83,7 @@ bool WebMContentEncodingsClient::OnListEnd(int id) {
|
||||||
// Default value of encoding order is 0, which should only be used on the
|
// Default value of encoding order is 0, which should only be used on the
|
||||||
// first ContentEncoding.
|
// first ContentEncoding.
|
||||||
if (!content_encodings_.empty()) {
|
if (!content_encodings_.empty()) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Missing ContentEncodingOrder.";
|
LOG(ERROR) << "Missing ContentEncodingOrder.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cur_content_encoding_->set_order(0);
|
cur_content_encoding_->set_order(0);
|
||||||
|
@ -100,15 +97,15 @@ bool WebMContentEncodingsClient::OnListEnd(int id) {
|
||||||
|
|
||||||
// Check for elements valid in spec but not supported for now.
|
// Check for elements valid in spec but not supported for now.
|
||||||
if (cur_content_encoding_->type() == ContentEncoding::kTypeCompression) {
|
if (cur_content_encoding_->type() == ContentEncoding::kTypeCompression) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "ContentCompression not supported.";
|
LOG(ERROR) << "ContentCompression not supported.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enforce mandatory elements without default values.
|
// Enforce mandatory elements without default values.
|
||||||
DCHECK(cur_content_encoding_->type() == ContentEncoding::kTypeEncryption);
|
DCHECK(cur_content_encoding_->type() == ContentEncoding::kTypeEncryption);
|
||||||
if (!content_encryption_encountered_) {
|
if (!content_encryption_encountered_) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "ContentEncodingType is encryption but"
|
LOG(ERROR) << "ContentEncodingType is encryption but"
|
||||||
<< " ContentEncryption is missing.";
|
<< " ContentEncryption is missing.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,19 +139,18 @@ bool WebMContentEncodingsClient::OnListEnd(int id) {
|
||||||
|
|
||||||
// Multiple occurrence restriction and range are checked in this function.
|
// Multiple occurrence restriction and range are checked in this function.
|
||||||
// Mandatory occurrence restriction is checked in OnListEnd.
|
// Mandatory occurrence restriction is checked in OnListEnd.
|
||||||
bool WebMContentEncodingsClient::OnUInt(int id, int64 val) {
|
bool WebMContentEncodingsClient::OnUInt(int id, int64_t val) {
|
||||||
DCHECK(cur_content_encoding_.get());
|
DCHECK(cur_content_encoding_.get());
|
||||||
|
|
||||||
if (id == kWebMIdContentEncodingOrder) {
|
if (id == kWebMIdContentEncodingOrder) {
|
||||||
if (cur_content_encoding_->order() != ContentEncoding::kOrderInvalid) {
|
if (cur_content_encoding_->order() != ContentEncoding::kOrderInvalid) {
|
||||||
MEDIA_LOG(ERROR, media_log_)
|
LOG(ERROR) << "Unexpected multiple ContentEncodingOrder.";
|
||||||
<< "Unexpected multiple ContentEncodingOrder.";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val != static_cast<int64>(content_encodings_.size())) {
|
if (val != static_cast<int64_t>(content_encodings_.size())) {
|
||||||
// According to the spec, encoding order starts with 0 and counts upwards.
|
// According to the spec, encoding order starts with 0 and counts upwards.
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unexpected ContentEncodingOrder.";
|
LOG(ERROR) << "Unexpected ContentEncodingOrder.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,20 +160,19 @@ bool WebMContentEncodingsClient::OnUInt(int id, int64 val) {
|
||||||
|
|
||||||
if (id == kWebMIdContentEncodingScope) {
|
if (id == kWebMIdContentEncodingScope) {
|
||||||
if (cur_content_encoding_->scope() != ContentEncoding::kScopeInvalid) {
|
if (cur_content_encoding_->scope() != ContentEncoding::kScopeInvalid) {
|
||||||
MEDIA_LOG(ERROR, media_log_)
|
LOG(ERROR) << "Unexpected multiple ContentEncodingScope.";
|
||||||
<< "Unexpected multiple ContentEncodingScope.";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val == ContentEncoding::kScopeInvalid ||
|
if (val == ContentEncoding::kScopeInvalid ||
|
||||||
val > ContentEncoding::kScopeMax) {
|
val > ContentEncoding::kScopeMax) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unexpected ContentEncodingScope.";
|
LOG(ERROR) << "Unexpected ContentEncodingScope.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val & ContentEncoding::kScopeNextContentEncodingData) {
|
if (val & ContentEncoding::kScopeNextContentEncodingData) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Encoded next ContentEncoding is not "
|
LOG(ERROR) << "Encoded next ContentEncoding is not "
|
||||||
"supported.";
|
"supported.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,19 +182,17 @@ bool WebMContentEncodingsClient::OnUInt(int id, int64 val) {
|
||||||
|
|
||||||
if (id == kWebMIdContentEncodingType) {
|
if (id == kWebMIdContentEncodingType) {
|
||||||
if (cur_content_encoding_->type() != ContentEncoding::kTypeInvalid) {
|
if (cur_content_encoding_->type() != ContentEncoding::kTypeInvalid) {
|
||||||
MEDIA_LOG(ERROR, media_log_)
|
LOG(ERROR) << "Unexpected multiple ContentEncodingType.";
|
||||||
<< "Unexpected multiple ContentEncodingType.";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val == ContentEncoding::kTypeCompression) {
|
if (val == ContentEncoding::kTypeCompression) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "ContentCompression not supported.";
|
LOG(ERROR) << "ContentCompression not supported.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val != ContentEncoding::kTypeEncryption) {
|
if (val != ContentEncoding::kTypeEncryption) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unexpected ContentEncodingType " << val
|
LOG(ERROR) << "Unexpected ContentEncodingType " << val << ".";
|
||||||
<< ".";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,14 +203,13 @@ bool WebMContentEncodingsClient::OnUInt(int id, int64 val) {
|
||||||
if (id == kWebMIdContentEncAlgo) {
|
if (id == kWebMIdContentEncAlgo) {
|
||||||
if (cur_content_encoding_->encryption_algo() !=
|
if (cur_content_encoding_->encryption_algo() !=
|
||||||
ContentEncoding::kEncAlgoInvalid) {
|
ContentEncoding::kEncAlgoInvalid) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unexpected multiple ContentEncAlgo.";
|
LOG(ERROR) << "Unexpected multiple ContentEncAlgo.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val < ContentEncoding::kEncAlgoNotEncrypted ||
|
if (val < ContentEncoding::kEncAlgoNotEncrypted ||
|
||||||
val > ContentEncoding::kEncAlgoAes) {
|
val > ContentEncoding::kEncAlgoAes) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unexpected ContentEncAlgo " << val
|
LOG(ERROR) << "Unexpected ContentEncAlgo " << val << ".";
|
||||||
<< ".";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,14 +221,12 @@ bool WebMContentEncodingsClient::OnUInt(int id, int64 val) {
|
||||||
if (id == kWebMIdAESSettingsCipherMode) {
|
if (id == kWebMIdAESSettingsCipherMode) {
|
||||||
if (cur_content_encoding_->cipher_mode() !=
|
if (cur_content_encoding_->cipher_mode() !=
|
||||||
ContentEncoding::kCipherModeInvalid) {
|
ContentEncoding::kCipherModeInvalid) {
|
||||||
MEDIA_LOG(ERROR, media_log_)
|
LOG(ERROR) << "Unexpected multiple AESSettingsCipherMode.";
|
||||||
<< "Unexpected multiple AESSettingsCipherMode.";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val != ContentEncoding::kCipherModeCtr) {
|
if (val != ContentEncoding::kCipherModeCtr) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unexpected AESSettingsCipherMode " << val
|
LOG(ERROR) << "Unexpected AESSettingsCipherMode " << val << ".";
|
||||||
<< ".";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,14 +242,16 @@ bool WebMContentEncodingsClient::OnUInt(int id, int64 val) {
|
||||||
|
|
||||||
// Multiple occurrence restriction is checked in this function. Mandatory
|
// Multiple occurrence restriction is checked in this function. Mandatory
|
||||||
// restriction is checked in OnListEnd.
|
// restriction is checked in OnListEnd.
|
||||||
bool WebMContentEncodingsClient::OnBinary(int id, const uint8* data, int size) {
|
bool WebMContentEncodingsClient::OnBinary(int id,
|
||||||
|
const uint8_t* data,
|
||||||
|
int size) {
|
||||||
DCHECK(cur_content_encoding_.get());
|
DCHECK(cur_content_encoding_.get());
|
||||||
DCHECK(data);
|
DCHECK(data);
|
||||||
DCHECK_GT(size, 0);
|
DCHECK_GT(size, 0);
|
||||||
|
|
||||||
if (id == kWebMIdContentEncKeyID) {
|
if (id == kWebMIdContentEncKeyID) {
|
||||||
if (!cur_content_encoding_->encryption_key_id().empty()) {
|
if (!cur_content_encoding_->encryption_key_id().empty()) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unexpected multiple ContentEncKeyID";
|
LOG(ERROR) << "Unexpected multiple ContentEncKeyID";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cur_content_encoding_->SetEncryptionKeyId(data, size);
|
cur_content_encoding_->SetEncryptionKeyId(data, size);
|
||||||
|
@ -272,3 +264,4 @@ bool WebMContentEncodingsClient::OnBinary(int id, const uint8* data, int size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -7,22 +7,21 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/callback.h"
|
#include "packager/base/callback.h"
|
||||||
#include "base/compiler_specific.h"
|
#include "packager/base/compiler_specific.h"
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
#include "media/base/media_export.h"
|
#include "packager/media/formats/webm/webm_content_encodings.h"
|
||||||
#include "media/base/media_log.h"
|
#include "packager/media/formats/webm/webm_parser.h"
|
||||||
#include "media/formats/webm/webm_content_encodings.h"
|
|
||||||
#include "media/formats/webm/webm_parser.h"
|
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
typedef std::vector<ContentEncoding*> ContentEncodings;
|
typedef std::vector<ContentEncoding*> ContentEncodings;
|
||||||
|
|
||||||
// Parser for WebM ContentEncodings element.
|
// Parser for WebM ContentEncodings element.
|
||||||
class MEDIA_EXPORT WebMContentEncodingsClient : public WebMParserClient {
|
class WebMContentEncodingsClient : public WebMParserClient {
|
||||||
public:
|
public:
|
||||||
explicit WebMContentEncodingsClient(const scoped_refptr<MediaLog>& media_log);
|
WebMContentEncodingsClient();
|
||||||
~WebMContentEncodingsClient() override;
|
~WebMContentEncodingsClient() override;
|
||||||
|
|
||||||
const ContentEncodings& content_encodings() const;
|
const ContentEncodings& content_encodings() const;
|
||||||
|
@ -30,11 +29,10 @@ class MEDIA_EXPORT WebMContentEncodingsClient : public WebMParserClient {
|
||||||
// WebMParserClient methods
|
// WebMParserClient methods
|
||||||
WebMParserClient* OnListStart(int id) override;
|
WebMParserClient* OnListStart(int id) override;
|
||||||
bool OnListEnd(int id) override;
|
bool OnListEnd(int id) override;
|
||||||
bool OnUInt(int id, int64 val) override;
|
bool OnUInt(int id, int64_t val) override;
|
||||||
bool OnBinary(int id, const uint8* data, int size) override;
|
bool OnBinary(int id, const uint8_t* data, int size) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
scoped_refptr<MediaLog> media_log_;
|
|
||||||
scoped_ptr<ContentEncoding> cur_content_encoding_;
|
scoped_ptr<ContentEncoding> cur_content_encoding_;
|
||||||
bool content_encryption_encountered_;
|
bool content_encryption_encountered_;
|
||||||
ContentEncodings content_encodings_;
|
ContentEncodings content_encodings_;
|
||||||
|
@ -46,5 +44,6 @@ class MEDIA_EXPORT WebMContentEncodingsClient : public WebMParserClient {
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_WEBM_CONTENT_ENCODINGS_CLIENT_H_
|
#endif // MEDIA_FORMATS_WEBM_WEBM_CONTENT_ENCODINGS_CLIENT_H_
|
||||||
|
|
|
@ -2,20 +2,21 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/webm_content_encodings_client.h"
|
#include "packager/media/formats/webm/webm_content_encodings_client.h"
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "base/bind.h"
|
#include "packager/base/bind.h"
|
||||||
#include "base/strings/string_number_conversions.h"
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
#include "media/base/mock_media_log.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
#include "media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_parser.h"
|
||||||
#include "media/formats/webm/webm_parser.h"
|
|
||||||
#include "testing/gmock/include/gmock/gmock.h"
|
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
|
||||||
|
|
||||||
using ::testing::StrictMock;
|
using ::testing::StrictMock;
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
// Matchers for verifying common media log entry strings.
|
// Matchers for verifying common media log entry strings.
|
||||||
|
@ -49,50 +50,46 @@ MATCHER_P(UnexpectedContentEncAlgo, algo, "") {
|
||||||
class WebMContentEncodingsClientTest : public testing::Test {
|
class WebMContentEncodingsClientTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
WebMContentEncodingsClientTest()
|
WebMContentEncodingsClientTest()
|
||||||
: media_log_(new StrictMock<MockMediaLog>()),
|
: client_(), parser_(kWebMIdContentEncodings, &client_) {}
|
||||||
client_(media_log_),
|
|
||||||
parser_(kWebMIdContentEncodings, &client_) {}
|
|
||||||
|
|
||||||
void ParseAndExpectToFail(const uint8* buf, int size) {
|
void ParseAndExpectToFail(const uint8_t* buf, int size) {
|
||||||
int result = parser_.Parse(buf, size);
|
int result = parser_.Parse(buf, size);
|
||||||
EXPECT_EQ(-1, result);
|
EXPECT_EQ(-1, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
scoped_refptr<StrictMock<MockMediaLog>> media_log_;
|
|
||||||
WebMContentEncodingsClient client_;
|
WebMContentEncodingsClient client_;
|
||||||
WebMListParser parser_;
|
WebMListParser parser_;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(WebMContentEncodingsClientTest, EmptyContentEncodings) {
|
TEST_F(WebMContentEncodingsClientTest, EmptyContentEncodings) {
|
||||||
const uint8 kContentEncodings[] = {
|
const uint8_t kContentEncodings[] = {
|
||||||
0x6D, 0x80, 0x80, // ContentEncodings (size = 0)
|
0x6D, 0x80, 0x80, // ContentEncodings (size = 0)
|
||||||
};
|
};
|
||||||
int size = sizeof(kContentEncodings);
|
int size = sizeof(kContentEncodings);
|
||||||
EXPECT_MEDIA_LOG(MissingContentEncoding());
|
|
||||||
ParseAndExpectToFail(kContentEncodings, size);
|
ParseAndExpectToFail(kContentEncodings, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMContentEncodingsClientTest, EmptyContentEncoding) {
|
TEST_F(WebMContentEncodingsClientTest, EmptyContentEncoding) {
|
||||||
const uint8 kContentEncodings[] = {
|
const uint8_t kContentEncodings[] = {
|
||||||
0x6D, 0x80, 0x83, // ContentEncodings (size = 3)
|
0x6D, 0x80, 0x83, // ContentEncodings (size = 3)
|
||||||
0x63, 0x40, 0x80, // ContentEncoding (size = 0)
|
0x63, 0x40, 0x80, // ContentEncoding (size = 0)
|
||||||
};
|
};
|
||||||
int size = sizeof(kContentEncodings);
|
int size = sizeof(kContentEncodings);
|
||||||
ParseAndExpectToFail(kContentEncodings, size);
|
ParseAndExpectToFail(kContentEncodings, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMContentEncodingsClientTest, SingleContentEncoding) {
|
TEST_F(WebMContentEncodingsClientTest, SingleContentEncoding) {
|
||||||
const uint8 kContentEncodings[] = {
|
const uint8_t kContentEncodings[] = {
|
||||||
0x6D, 0x80, 0xA1, // ContentEncodings (size = 33)
|
0x6D, 0x80, 0xA1, // ContentEncodings (size = 33)
|
||||||
0x62, 0x40, 0x9e, // ContentEncoding (size = 30)
|
0x62, 0x40, 0x9e, // ContentEncoding (size = 30)
|
||||||
0x50, 0x31, 0x81, 0x00, // ContentEncodingOrder (size = 1)
|
0x50, 0x31, 0x81, 0x00, // ContentEncodingOrder (size = 1)
|
||||||
0x50, 0x32, 0x81, 0x01, // ContentEncodingScope (size = 1)
|
0x50, 0x32, 0x81, 0x01, // ContentEncodingScope (size = 1)
|
||||||
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
||||||
0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
|
0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
|
||||||
0x47, 0xE1, 0x81, 0x05, // ContentEncAlgo (size = 1)
|
0x47, 0xE1, 0x81, 0x05, // ContentEncAlgo (size = 1)
|
||||||
0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
|
0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
|
||||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||||
};
|
};
|
||||||
int size = sizeof(kContentEncodings);
|
int size = sizeof(kContentEncodings);
|
||||||
|
|
||||||
|
@ -112,24 +109,24 @@ TEST_F(WebMContentEncodingsClientTest, SingleContentEncoding) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMContentEncodingsClientTest, MultipleContentEncoding) {
|
TEST_F(WebMContentEncodingsClientTest, MultipleContentEncoding) {
|
||||||
const uint8 kContentEncodings[] = {
|
const uint8_t kContentEncodings[] = {
|
||||||
0x6D, 0x80, 0xC2, // ContentEncodings (size = 66)
|
0x6D, 0x80, 0xC2, // ContentEncodings (size = 66)
|
||||||
0x62, 0x40, 0x9e, // ContentEncoding (size = 30)
|
0x62, 0x40, 0x9e, // ContentEncoding (size = 30)
|
||||||
0x50, 0x31, 0x81, 0x00, // ContentEncodingOrder (size = 1)
|
0x50, 0x31, 0x81, 0x00, // ContentEncodingOrder (size = 1)
|
||||||
0x50, 0x32, 0x81, 0x03, // ContentEncodingScope (size = 1)
|
0x50, 0x32, 0x81, 0x03, // ContentEncodingScope (size = 1)
|
||||||
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
||||||
0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
|
0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
|
||||||
0x47, 0xE1, 0x81, 0x05, // ContentEncAlgo (size = 1)
|
0x47, 0xE1, 0x81, 0x05, // ContentEncAlgo (size = 1)
|
||||||
0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
|
0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
|
||||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||||
0x62, 0x40, 0x9e, // ContentEncoding (size = 30)
|
0x62, 0x40, 0x9e, // ContentEncoding (size = 30)
|
||||||
0x50, 0x31, 0x81, 0x01, // ContentEncodingOrder (size = 1)
|
0x50, 0x31, 0x81, 0x01, // ContentEncodingOrder (size = 1)
|
||||||
0x50, 0x32, 0x81, 0x03, // ContentEncodingScope (size = 1)
|
0x50, 0x32, 0x81, 0x03, // ContentEncodingScope (size = 1)
|
||||||
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
||||||
0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
|
0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
|
||||||
0x47, 0xE1, 0x81, 0x01, // ContentEncAlgo (size = 1)
|
0x47, 0xE1, 0x81, 0x01, // ContentEncAlgo (size = 1)
|
||||||
0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
|
0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
|
||||||
0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
|
0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
|
||||||
};
|
};
|
||||||
int size = sizeof(kContentEncodings);
|
int size = sizeof(kContentEncodings);
|
||||||
|
|
||||||
|
@ -152,14 +149,14 @@ TEST_F(WebMContentEncodingsClientTest, MultipleContentEncoding) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMContentEncodingsClientTest, DefaultValues) {
|
TEST_F(WebMContentEncodingsClientTest, DefaultValues) {
|
||||||
const uint8 kContentEncodings[] = {
|
const uint8_t kContentEncodings[] = {
|
||||||
0x6D, 0x80, 0x8A, // ContentEncodings (size = 10)
|
0x6D, 0x80, 0x8A, // ContentEncodings (size = 10)
|
||||||
0x62, 0x40, 0x87, // ContentEncoding (size = 7)
|
0x62, 0x40, 0x87, // ContentEncoding (size = 7)
|
||||||
// ContentEncodingOrder missing
|
// ContentEncodingOrder missing
|
||||||
// ContentEncodingScope missing
|
// ContentEncodingScope missing
|
||||||
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
||||||
0x50, 0x35, 0x80, // ContentEncryption (size = 0)
|
0x50, 0x35, 0x80, // ContentEncryption (size = 0)
|
||||||
// ContentEncAlgo missing
|
// ContentEncAlgo missing
|
||||||
};
|
};
|
||||||
int size = sizeof(kContentEncodings);
|
int size = sizeof(kContentEncodings);
|
||||||
|
|
||||||
|
@ -179,16 +176,16 @@ TEST_F(WebMContentEncodingsClientTest, DefaultValues) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMContentEncodingsClientTest, ContentEncodingsClientReuse) {
|
TEST_F(WebMContentEncodingsClientTest, ContentEncodingsClientReuse) {
|
||||||
const uint8 kContentEncodings[] = {
|
const uint8_t kContentEncodings[] = {
|
||||||
0x6D, 0x80, 0xA1, // ContentEncodings (size = 33)
|
0x6D, 0x80, 0xA1, // ContentEncodings (size = 33)
|
||||||
0x62, 0x40, 0x9e, // ContentEncoding (size = 30)
|
0x62, 0x40, 0x9e, // ContentEncoding (size = 30)
|
||||||
0x50, 0x31, 0x81, 0x00, // ContentEncodingOrder (size = 1)
|
0x50, 0x31, 0x81, 0x00, // ContentEncodingOrder (size = 1)
|
||||||
0x50, 0x32, 0x81, 0x01, // ContentEncodingScope (size = 1)
|
0x50, 0x32, 0x81, 0x01, // ContentEncodingScope (size = 1)
|
||||||
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
||||||
0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
|
0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
|
||||||
0x47, 0xE1, 0x81, 0x05, // ContentEncAlgo (size = 1)
|
0x47, 0xE1, 0x81, 0x05, // ContentEncAlgo (size = 1)
|
||||||
0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
|
0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
|
||||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||||
};
|
};
|
||||||
int size = sizeof(kContentEncodings);
|
int size = sizeof(kContentEncodings);
|
||||||
|
|
||||||
|
@ -214,69 +211,65 @@ TEST_F(WebMContentEncodingsClientTest, ContentEncodingsClientReuse) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMContentEncodingsClientTest, InvalidContentEncodingOrder) {
|
TEST_F(WebMContentEncodingsClientTest, InvalidContentEncodingOrder) {
|
||||||
const uint8 kContentEncodings[] = {
|
const uint8_t kContentEncodings[] = {
|
||||||
0x6D, 0x80, 0x8E, // ContentEncodings (size = 14)
|
0x6D, 0x80, 0x8E, // ContentEncodings (size = 14)
|
||||||
0x62, 0x40, 0x8B, // ContentEncoding (size = 11)
|
0x62, 0x40, 0x8B, // ContentEncoding (size = 11)
|
||||||
0x50, 0x31, 0x81, 0xEE, // ContentEncodingOrder (size = 1), invalid
|
0x50, 0x31, 0x81, 0xEE, // ContentEncodingOrder (size = 1), invalid
|
||||||
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
||||||
0x50, 0x35, 0x80, // ContentEncryption (size = 0)
|
0x50, 0x35, 0x80, // ContentEncryption (size = 0)
|
||||||
};
|
};
|
||||||
int size = sizeof(kContentEncodings);
|
int size = sizeof(kContentEncodings);
|
||||||
EXPECT_MEDIA_LOG(UnexpectedContentEncodingOrder());
|
|
||||||
ParseAndExpectToFail(kContentEncodings, size);
|
ParseAndExpectToFail(kContentEncodings, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMContentEncodingsClientTest, InvalidContentEncodingScope) {
|
TEST_F(WebMContentEncodingsClientTest, InvalidContentEncodingScope) {
|
||||||
const uint8 kContentEncodings[] = {
|
const uint8_t kContentEncodings[] = {
|
||||||
0x6D, 0x80, 0x8E, // ContentEncodings (size = 14)
|
0x6D, 0x80, 0x8E, // ContentEncodings (size = 14)
|
||||||
0x62, 0x40, 0x8B, // ContentEncoding (size = 11)
|
0x62, 0x40, 0x8B, // ContentEncoding (size = 11)
|
||||||
0x50, 0x32, 0x81, 0xEE, // ContentEncodingScope (size = 1), invalid
|
0x50, 0x32, 0x81, 0xEE, // ContentEncodingScope (size = 1), invalid
|
||||||
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
||||||
0x50, 0x35, 0x80, // ContentEncryption (size = 0)
|
0x50, 0x35, 0x80, // ContentEncryption (size = 0)
|
||||||
};
|
};
|
||||||
int size = sizeof(kContentEncodings);
|
int size = sizeof(kContentEncodings);
|
||||||
EXPECT_MEDIA_LOG(UnexpectedContentEncodingScope());
|
|
||||||
ParseAndExpectToFail(kContentEncodings, size);
|
ParseAndExpectToFail(kContentEncodings, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMContentEncodingsClientTest, InvalidContentEncodingType) {
|
TEST_F(WebMContentEncodingsClientTest, InvalidContentEncodingType) {
|
||||||
const uint8 kContentEncodings[] = {
|
const uint8_t kContentEncodings[] = {
|
||||||
0x6D, 0x80, 0x8E, // ContentEncodings (size = 14)
|
0x6D, 0x80, 0x8E, // ContentEncodings (size = 14)
|
||||||
0x62, 0x40, 0x8B, // ContentEncoding (size = 11)
|
0x62, 0x40, 0x8B, // ContentEncoding (size = 11)
|
||||||
0x50, 0x33, 0x81, 0x00, // ContentEncodingType (size = 1), invalid
|
0x50, 0x33, 0x81, 0x00, // ContentEncodingType (size = 1), invalid
|
||||||
0x50, 0x35, 0x80, // ContentEncryption (size = 0)
|
0x50, 0x35, 0x80, // ContentEncryption (size = 0)
|
||||||
};
|
};
|
||||||
int size = sizeof(kContentEncodings);
|
int size = sizeof(kContentEncodings);
|
||||||
EXPECT_MEDIA_LOG(ContentCompressionNotSupported());
|
|
||||||
ParseAndExpectToFail(kContentEncodings, size);
|
ParseAndExpectToFail(kContentEncodings, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContentEncodingType is encryption but no ContentEncryption present.
|
// ContentEncodingType is encryption but no ContentEncryption present.
|
||||||
TEST_F(WebMContentEncodingsClientTest, MissingContentEncryption) {
|
TEST_F(WebMContentEncodingsClientTest, MissingContentEncryption) {
|
||||||
const uint8 kContentEncodings[] = {
|
const uint8_t kContentEncodings[] = {
|
||||||
0x6D, 0x80, 0x87, // ContentEncodings (size = 7)
|
0x6D, 0x80, 0x87, // ContentEncodings (size = 7)
|
||||||
0x62, 0x40, 0x84, // ContentEncoding (size = 4)
|
0x62, 0x40, 0x84, // ContentEncoding (size = 4)
|
||||||
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
||||||
// ContentEncryption missing
|
// ContentEncryption missing
|
||||||
};
|
};
|
||||||
int size = sizeof(kContentEncodings);
|
int size = sizeof(kContentEncodings);
|
||||||
EXPECT_MEDIA_LOG(MissingContentEncryption());
|
|
||||||
ParseAndExpectToFail(kContentEncodings, size);
|
ParseAndExpectToFail(kContentEncodings, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMContentEncodingsClientTest, InvalidContentEncAlgo) {
|
TEST_F(WebMContentEncodingsClientTest, InvalidContentEncAlgo) {
|
||||||
const uint8 kContentEncodings[] = {
|
const uint8_t kContentEncodings[] = {
|
||||||
0x6D, 0x80, 0x99, // ContentEncodings (size = 25)
|
0x6D, 0x80, 0x99, // ContentEncodings (size = 25)
|
||||||
0x62, 0x40, 0x96, // ContentEncoding (size = 22)
|
0x62, 0x40, 0x96, // ContentEncoding (size = 22)
|
||||||
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1)
|
||||||
0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
|
0x50, 0x35, 0x8F, // ContentEncryption (size = 15)
|
||||||
0x47, 0xE1, 0x81, 0xEE, // ContentEncAlgo (size = 1), invalid
|
0x47, 0xE1, 0x81, 0xEE, // ContentEncAlgo (size = 1), invalid
|
||||||
0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
|
0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8)
|
||||||
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
|
||||||
};
|
};
|
||||||
int size = sizeof(kContentEncodings);
|
int size = sizeof(kContentEncodings);
|
||||||
EXPECT_MEDIA_LOG(UnexpectedContentEncAlgo(0xEE));
|
|
||||||
ParseAndExpectToFail(kContentEncodings, size);
|
ParseAndExpectToFail(kContentEncodings, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -2,13 +2,14 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/webm_crypto_helpers.h"
|
#include "packager/media/formats/webm/webm_crypto_helpers.h"
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "base/sys_byteorder.h"
|
#include "packager/base/sys_byteorder.h"
|
||||||
#include "media/base/decrypt_config.h"
|
#include "packager/media/base/decrypt_config.h"
|
||||||
#include "media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ namespace {
|
||||||
// CTR IV appended with a CTR block counter. |iv| is an 8 byte CTR IV.
|
// CTR IV appended with a CTR block counter. |iv| is an 8 byte CTR IV.
|
||||||
// |iv_size| is the size of |iv| in btyes. Returns a string of
|
// |iv_size| is the size of |iv| in btyes. Returns a string of
|
||||||
// kDecryptionKeySize bytes.
|
// kDecryptionKeySize bytes.
|
||||||
std::string GenerateWebMCounterBlock(const uint8* iv, int iv_size) {
|
std::string GenerateWebMCounterBlock(const uint8_t* iv, int iv_size) {
|
||||||
std::string counter_block(reinterpret_cast<const char*>(iv), iv_size);
|
std::string counter_block(reinterpret_cast<const char*>(iv), iv_size);
|
||||||
counter_block.append(DecryptConfig::kDecryptionKeySize - iv_size, 0);
|
counter_block.append(DecryptConfig::kDecryptionKeySize - iv_size, 0);
|
||||||
return counter_block;
|
return counter_block;
|
||||||
|
@ -24,8 +25,10 @@ std::string GenerateWebMCounterBlock(const uint8* iv, int iv_size) {
|
||||||
|
|
||||||
} // namespace anonymous
|
} // namespace anonymous
|
||||||
|
|
||||||
bool WebMCreateDecryptConfig(const uint8* data, int data_size,
|
bool WebMCreateDecryptConfig(const uint8_t* data,
|
||||||
const uint8* key_id, int key_id_size,
|
int data_size,
|
||||||
|
const uint8_t* key_id,
|
||||||
|
int key_id_size,
|
||||||
scoped_ptr<DecryptConfig>* decrypt_config,
|
scoped_ptr<DecryptConfig>* decrypt_config,
|
||||||
int* data_offset) {
|
int* data_offset) {
|
||||||
if (data_size < kWebMSignalByteSize) {
|
if (data_size < kWebMSignalByteSize) {
|
||||||
|
@ -33,7 +36,7 @@ bool WebMCreateDecryptConfig(const uint8* data, int data_size,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 signal_byte = data[0];
|
uint8_t signal_byte = data[0];
|
||||||
int frame_offset = sizeof(signal_byte);
|
int frame_offset = sizeof(signal_byte);
|
||||||
|
|
||||||
// Setting the DecryptConfig object of the buffer while leaving the
|
// Setting the DecryptConfig object of the buffer while leaving the
|
||||||
|
@ -60,3 +63,4 @@ bool WebMCreateDecryptConfig(const uint8* data, int data_size,
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -5,10 +5,13 @@
|
||||||
#ifndef MEDIA_FORMATS_WEBM_WEBM_CRYPTO_HELPERS_H_
|
#ifndef MEDIA_FORMATS_WEBM_WEBM_CRYPTO_HELPERS_H_
|
||||||
#define MEDIA_FORMATS_WEBM_WEBM_CRYPTO_HELPERS_H_
|
#define MEDIA_FORMATS_WEBM_WEBM_CRYPTO_HELPERS_H_
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include <stdint.h>
|
||||||
#include "base/memory/scoped_ptr.h"
|
|
||||||
#include "media/base/decoder_buffer.h"
|
|
||||||
|
|
||||||
|
#include "packager/base/macros.h"
|
||||||
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
|
#include "packager/media/base/decoder_buffer.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
// Fills an initialized DecryptConfig, which can be sent to the Decryptor if
|
// Fills an initialized DecryptConfig, which can be sent to the Decryptor if
|
||||||
|
@ -18,11 +21,14 @@ namespace media {
|
||||||
// false otherwise, in which case |decrypt_config| and |data_offset| will not be
|
// false otherwise, in which case |decrypt_config| and |data_offset| will not be
|
||||||
// changed. Current encrypted WebM request for comments specification is here
|
// changed. Current encrypted WebM request for comments specification is here
|
||||||
// http://wiki.webmproject.org/encryption/webm-encryption-rfc
|
// http://wiki.webmproject.org/encryption/webm-encryption-rfc
|
||||||
bool WebMCreateDecryptConfig(const uint8* data, int data_size,
|
bool WebMCreateDecryptConfig(const uint8_t* data,
|
||||||
const uint8* key_id, int key_id_size,
|
int data_size,
|
||||||
|
const uint8_t* key_id,
|
||||||
|
int key_id_size,
|
||||||
scoped_ptr<DecryptConfig>* decrypt_config,
|
scoped_ptr<DecryptConfig>* decrypt_config,
|
||||||
int* data_offset);
|
int* data_offset);
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_WEBM_CRYPT_HELPERS_H_
|
#endif // MEDIA_FORMATS_WEBM_WEBM_CRYPT_HELPERS_H_
|
||||||
|
|
|
@ -2,11 +2,12 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/webm_info_parser.h"
|
#include "packager/media/formats/webm/webm_info_parser.h"
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
// Default timecode scale if the TimecodeScale element is
|
// Default timecode scale if the TimecodeScale element is
|
||||||
|
@ -20,7 +21,7 @@ WebMInfoParser::WebMInfoParser()
|
||||||
|
|
||||||
WebMInfoParser::~WebMInfoParser() {}
|
WebMInfoParser::~WebMInfoParser() {}
|
||||||
|
|
||||||
int WebMInfoParser::Parse(const uint8* buf, int size) {
|
int WebMInfoParser::Parse(const uint8_t* buf, int size) {
|
||||||
timecode_scale_ = -1;
|
timecode_scale_ = -1;
|
||||||
duration_ = -1;
|
duration_ = -1;
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ bool WebMInfoParser::OnListEnd(int id) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMInfoParser::OnUInt(int id, int64 val) {
|
bool WebMInfoParser::OnUInt(int id, int64_t val) {
|
||||||
if (id != kWebMIdTimecodeScale)
|
if (id != kWebMIdTimecodeScale)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -73,12 +74,12 @@ bool WebMInfoParser::OnFloat(int id, double val) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMInfoParser::OnBinary(int id, const uint8* data, int size) {
|
bool WebMInfoParser::OnBinary(int id, const uint8_t* data, int size) {
|
||||||
if (id == kWebMIdDateUTC) {
|
if (id == kWebMIdDateUTC) {
|
||||||
if (size != 8)
|
if (size != 8)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int64 date_in_nanoseconds = 0;
|
int64_t date_in_nanoseconds = 0;
|
||||||
for (int i = 0; i < size; ++i)
|
for (int i = 0; i < size; ++i)
|
||||||
date_in_nanoseconds = (date_in_nanoseconds << 8) | data[i];
|
date_in_nanoseconds = (date_in_nanoseconds << 8) | data[i];
|
||||||
|
|
||||||
|
@ -101,3 +102,4 @@ bool WebMInfoParser::OnString(int id, const std::string& str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -5,15 +5,15 @@
|
||||||
#ifndef MEDIA_FORMATS_WEBM_WEBM_INFO_PARSER_H_
|
#ifndef MEDIA_FORMATS_WEBM_WEBM_INFO_PARSER_H_
|
||||||
#define MEDIA_FORMATS_WEBM_WEBM_INFO_PARSER_H_
|
#define MEDIA_FORMATS_WEBM_WEBM_INFO_PARSER_H_
|
||||||
|
|
||||||
#include "base/compiler_specific.h"
|
#include "packager/base/compiler_specific.h"
|
||||||
#include "base/time/time.h"
|
#include "packager/base/time/time.h"
|
||||||
#include "media/base/media_export.h"
|
#include "packager/media/formats/webm/webm_parser.h"
|
||||||
#include "media/formats/webm/webm_parser.h"
|
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
// Parser for WebM Info element.
|
// Parser for WebM Info element.
|
||||||
class MEDIA_EXPORT WebMInfoParser : public WebMParserClient {
|
class WebMInfoParser : public WebMParserClient {
|
||||||
public:
|
public:
|
||||||
WebMInfoParser();
|
WebMInfoParser();
|
||||||
~WebMInfoParser() override;
|
~WebMInfoParser() override;
|
||||||
|
@ -23,9 +23,9 @@ class MEDIA_EXPORT WebMInfoParser : public WebMParserClient {
|
||||||
// Returns -1 if the parse fails.
|
// Returns -1 if the parse fails.
|
||||||
// Returns 0 if more data is needed.
|
// Returns 0 if more data is needed.
|
||||||
// Returns the number of bytes parsed on success.
|
// Returns the number of bytes parsed on success.
|
||||||
int Parse(const uint8* buf, int size);
|
int Parse(const uint8_t* buf, int size);
|
||||||
|
|
||||||
int64 timecode_scale() const { return timecode_scale_; }
|
int64_t timecode_scale() const { return timecode_scale_; }
|
||||||
double duration() const { return duration_; }
|
double duration() const { return duration_; }
|
||||||
base::Time date_utc() const { return date_utc_; }
|
base::Time date_utc() const { return date_utc_; }
|
||||||
|
|
||||||
|
@ -33,12 +33,12 @@ class MEDIA_EXPORT WebMInfoParser : public WebMParserClient {
|
||||||
// WebMParserClient methods
|
// WebMParserClient methods
|
||||||
WebMParserClient* OnListStart(int id) override;
|
WebMParserClient* OnListStart(int id) override;
|
||||||
bool OnListEnd(int id) override;
|
bool OnListEnd(int id) override;
|
||||||
bool OnUInt(int id, int64 val) override;
|
bool OnUInt(int id, int64_t val) override;
|
||||||
bool OnFloat(int id, double val) override;
|
bool OnFloat(int id, double val) override;
|
||||||
bool OnBinary(int id, const uint8* data, int size) override;
|
bool OnBinary(int id, const uint8_t* data, int size) override;
|
||||||
bool OnString(int id, const std::string& str) override;
|
bool OnString(int id, const std::string& str) override;
|
||||||
|
|
||||||
int64 timecode_scale_;
|
int64_t timecode_scale_;
|
||||||
double duration_;
|
double duration_;
|
||||||
base::Time date_utc_;
|
base::Time date_utc_;
|
||||||
|
|
||||||
|
@ -46,5 +46,6 @@ class MEDIA_EXPORT WebMInfoParser : public WebMParserClient {
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_WEBM_INFO_PARSER_H_
|
#endif // MEDIA_FORMATS_WEBM_WEBM_INFO_PARSER_H_
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/webm_parser.h"
|
#include "packager/media/formats/webm/webm_parser.h"
|
||||||
|
|
||||||
// This file contains code to parse WebM file elements. It was created
|
// This file contains code to parse WebM file elements. It was created
|
||||||
// from information in the Matroska spec.
|
// from information in the Matroska spec.
|
||||||
|
@ -13,10 +13,11 @@
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "base/numerics/safe_conversions.h"
|
#include "packager/base/numerics/safe_conversions.h"
|
||||||
#include "media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
enum ElementType {
|
enum ElementType {
|
||||||
|
@ -423,9 +424,11 @@ static const ListElementInfo kListElementInfo[] = {
|
||||||
// element size fields and is false for ID field values.
|
// element size fields and is false for ID field values.
|
||||||
//
|
//
|
||||||
// Returns: The number of bytes parsed on success. -1 on error.
|
// Returns: The number of bytes parsed on success. -1 on error.
|
||||||
static int ParseWebMElementHeaderField(const uint8* buf, int size,
|
static int ParseWebMElementHeaderField(const uint8_t* buf,
|
||||||
int max_bytes, bool mask_first_byte,
|
int size,
|
||||||
int64* num) {
|
int max_bytes,
|
||||||
|
bool mask_first_byte,
|
||||||
|
int64_t* num) {
|
||||||
DCHECK(buf);
|
DCHECK(buf);
|
||||||
DCHECK(num);
|
DCHECK(num);
|
||||||
|
|
||||||
|
@ -436,7 +439,7 @@ static int ParseWebMElementHeaderField(const uint8* buf, int size,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int mask = 0x80;
|
int mask = 0x80;
|
||||||
uint8 ch = buf[0];
|
uint8_t ch = buf[0];
|
||||||
int extra_bytes = -1;
|
int extra_bytes = -1;
|
||||||
bool all_ones = false;
|
bool all_ones = false;
|
||||||
for (int i = 0; i < max_bytes; ++i) {
|
for (int i = 0; i < max_bytes; ++i) {
|
||||||
|
@ -471,8 +474,10 @@ static int ParseWebMElementHeaderField(const uint8* buf, int size,
|
||||||
return bytes_used;
|
return bytes_used;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WebMParseElementHeader(const uint8* buf, int size,
|
int WebMParseElementHeader(const uint8_t* buf,
|
||||||
int* id, int64* element_size) {
|
int size,
|
||||||
|
int* id,
|
||||||
|
int64_t* element_size) {
|
||||||
DCHECK(buf);
|
DCHECK(buf);
|
||||||
DCHECK_GE(size, 0);
|
DCHECK_GE(size, 0);
|
||||||
DCHECK(id);
|
DCHECK(id);
|
||||||
|
@ -481,7 +486,7 @@ int WebMParseElementHeader(const uint8* buf, int size,
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int64 tmp = 0;
|
int64_t tmp = 0;
|
||||||
int num_id_bytes = ParseWebMElementHeaderField(buf, size, 4, false, &tmp);
|
int num_id_bytes = ParseWebMElementHeaderField(buf, size, 4, false, &tmp);
|
||||||
|
|
||||||
if (num_id_bytes <= 0)
|
if (num_id_bytes <= 0)
|
||||||
|
@ -543,19 +548,22 @@ static int FindListLevel(int id) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ParseUInt(const uint8* buf, int size, int id,
|
static int ParseUInt(const uint8_t* buf,
|
||||||
|
int size,
|
||||||
|
int id,
|
||||||
WebMParserClient* client) {
|
WebMParserClient* client) {
|
||||||
if ((size <= 0) || (size > 8))
|
if ((size <= 0) || (size > 8))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// Read in the big-endian integer.
|
// Read in the big-endian integer.
|
||||||
uint64 value = 0;
|
uint64_t value = 0;
|
||||||
for (int i = 0; i < size; ++i)
|
for (int i = 0; i < size; ++i)
|
||||||
value = (value << 8) | buf[i];
|
value = (value << 8) | buf[i];
|
||||||
|
|
||||||
// We use int64 in place of uint64 everywhere for convenience. See this bug
|
// We use int64_t in place of uint64_t everywhere for convenience. See this
|
||||||
|
// bug
|
||||||
// for more details: http://crbug.com/366750#c3
|
// for more details: http://crbug.com/366750#c3
|
||||||
if (!base::IsValueInRangeForNumericType<int64>(value))
|
if (!base::IsValueInRangeForNumericType<int64_t>(value))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!client->OnUInt(id, value))
|
if (!client->OnUInt(id, value))
|
||||||
|
@ -564,16 +572,17 @@ static int ParseUInt(const uint8* buf, int size, int id,
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ParseFloat(const uint8* buf, int size, int id,
|
static int ParseFloat(const uint8_t* buf,
|
||||||
|
int size,
|
||||||
|
int id,
|
||||||
WebMParserClient* client) {
|
WebMParserClient* client) {
|
||||||
|
|
||||||
if ((size != 4) && (size != 8))
|
if ((size != 4) && (size != 8))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
double value = -1;
|
double value = -1;
|
||||||
|
|
||||||
// Read the bytes from big-endian form into a native endian integer.
|
// Read the bytes from big-endian form into a native endian integer.
|
||||||
int64 tmp = 0;
|
int64_t tmp = 0;
|
||||||
for (int i = 0; i < size; ++i)
|
for (int i = 0; i < size; ++i)
|
||||||
tmp = (tmp << 8) | buf[i];
|
tmp = (tmp << 8) | buf[i];
|
||||||
|
|
||||||
|
@ -581,14 +590,14 @@ static int ParseFloat(const uint8* buf, int size, int id,
|
||||||
// number.
|
// number.
|
||||||
if (size == 4) {
|
if (size == 4) {
|
||||||
union {
|
union {
|
||||||
int32 src;
|
int32_t src;
|
||||||
float dst;
|
float dst;
|
||||||
} tmp2;
|
} tmp2;
|
||||||
tmp2.src = static_cast<int32>(tmp);
|
tmp2.src = static_cast<int32_t>(tmp);
|
||||||
value = tmp2.dst;
|
value = tmp2.dst;
|
||||||
} else if (size == 8) {
|
} else if (size == 8) {
|
||||||
union {
|
union {
|
||||||
int64 src;
|
int64_t src;
|
||||||
double dst;
|
double dst;
|
||||||
} tmp2;
|
} tmp2;
|
||||||
tmp2.src = tmp;
|
tmp2.src = tmp;
|
||||||
|
@ -603,21 +612,28 @@ static int ParseFloat(const uint8* buf, int size, int id,
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ParseBinary(const uint8* buf, int size, int id,
|
static int ParseBinary(const uint8_t* buf,
|
||||||
|
int size,
|
||||||
|
int id,
|
||||||
WebMParserClient* client) {
|
WebMParserClient* client) {
|
||||||
return client->OnBinary(id, buf, size) ? size : -1;
|
return client->OnBinary(id, buf, size) ? size : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ParseString(const uint8* buf, int size, int id,
|
static int ParseString(const uint8_t* buf,
|
||||||
|
int size,
|
||||||
|
int id,
|
||||||
WebMParserClient* client) {
|
WebMParserClient* client) {
|
||||||
const uint8* end = static_cast<const uint8*>(memchr(buf, '\0', size));
|
const uint8_t* end = static_cast<const uint8_t*>(memchr(buf, '\0', size));
|
||||||
int length = (end != NULL) ? static_cast<int>(end - buf) : size;
|
int length = (end != NULL) ? static_cast<int>(end - buf) : size;
|
||||||
std::string str(reinterpret_cast<const char*>(buf), length);
|
std::string str(reinterpret_cast<const char*>(buf), length);
|
||||||
return client->OnString(id, str) ? size : -1;
|
return client->OnString(id, str) ? size : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ParseNonListElement(ElementType type, int id, int64 element_size,
|
static int ParseNonListElement(ElementType type,
|
||||||
const uint8* buf, int size,
|
int id,
|
||||||
|
int64_t element_size,
|
||||||
|
const uint8_t* buf,
|
||||||
|
int size,
|
||||||
WebMParserClient* client) {
|
WebMParserClient* client) {
|
||||||
DCHECK_GE(size, element_size);
|
DCHECK_GE(size, element_size);
|
||||||
|
|
||||||
|
@ -664,7 +680,7 @@ bool WebMParserClient::OnListEnd(int id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMParserClient::OnUInt(int id, int64 val) {
|
bool WebMParserClient::OnUInt(int id, int64_t val) {
|
||||||
DVLOG(1) << "Unexpected unsigned integer element with ID " << std::hex << id;
|
DVLOG(1) << "Unexpected unsigned integer element with ID " << std::hex << id;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -674,7 +690,7 @@ bool WebMParserClient::OnFloat(int id, double val) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMParserClient::OnBinary(int id, const uint8* data, int size) {
|
bool WebMParserClient::OnBinary(int id, const uint8_t* data, int size) {
|
||||||
DVLOG(1) << "Unexpected binary element with ID " << std::hex << id;
|
DVLOG(1) << "Unexpected binary element with ID " << std::hex << id;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -700,7 +716,7 @@ void WebMListParser::Reset() {
|
||||||
list_state_stack_.clear();
|
list_state_stack_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int WebMListParser::Parse(const uint8* buf, int size) {
|
int WebMListParser::Parse(const uint8_t* buf, int size) {
|
||||||
DCHECK(buf);
|
DCHECK(buf);
|
||||||
|
|
||||||
if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST)
|
if (size < 0 || state_ == PARSE_ERROR || state_ == DONE_PARSING_LIST)
|
||||||
|
@ -709,13 +725,13 @@ int WebMListParser::Parse(const uint8* buf, int size) {
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const uint8* cur = buf;
|
const uint8_t* cur = buf;
|
||||||
int cur_size = size;
|
int cur_size = size;
|
||||||
int bytes_parsed = 0;
|
int bytes_parsed = 0;
|
||||||
|
|
||||||
while (cur_size > 0 && state_ != PARSE_ERROR && state_ != DONE_PARSING_LIST) {
|
while (cur_size > 0 && state_ != PARSE_ERROR && state_ != DONE_PARSING_LIST) {
|
||||||
int element_id = 0;
|
int element_id = 0;
|
||||||
int64 element_size = 0;
|
int64_t element_size = 0;
|
||||||
int result = WebMParseElementHeader(cur, cur_size, &element_id,
|
int result = WebMParseElementHeader(cur, cur_size, &element_id,
|
||||||
&element_size);
|
&element_size);
|
||||||
|
|
||||||
|
@ -749,7 +765,7 @@ int WebMListParser::Parse(const uint8* buf, int size) {
|
||||||
|
|
||||||
case INSIDE_LIST: {
|
case INSIDE_LIST: {
|
||||||
int header_size = result;
|
int header_size = result;
|
||||||
const uint8* element_data = cur + header_size;
|
const uint8_t* element_data = cur + header_size;
|
||||||
int element_data_size = cur_size - header_size;
|
int element_data_size = cur_size - header_size;
|
||||||
|
|
||||||
if (element_size < element_data_size)
|
if (element_size < element_data_size)
|
||||||
|
@ -793,8 +809,10 @@ void WebMListParser::ChangeState(State new_state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int WebMListParser::ParseListElement(int header_size,
|
int WebMListParser::ParseListElement(int header_size,
|
||||||
int id, int64 element_size,
|
int id,
|
||||||
const uint8* data, int size) {
|
int64_t element_size,
|
||||||
|
const uint8_t* data,
|
||||||
|
int size) {
|
||||||
DCHECK_GT(list_state_stack_.size(), 0u);
|
DCHECK_GT(list_state_stack_.size(), 0u);
|
||||||
|
|
||||||
ListState& list_state = list_state_stack_.back();
|
ListState& list_state = list_state_stack_.back();
|
||||||
|
@ -827,7 +845,7 @@ int WebMListParser::ParseListElement(int header_size,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the whole element can fit inside the current list.
|
// Make sure the whole element can fit inside the current list.
|
||||||
int64 total_element_size = header_size + element_size;
|
int64_t total_element_size = header_size + element_size;
|
||||||
if (list_state.size_ != kWebMUnknownSize &&
|
if (list_state.size_ != kWebMUnknownSize &&
|
||||||
list_state.size_ < list_state.bytes_parsed_ + total_element_size) {
|
list_state.size_ < list_state.bytes_parsed_ + total_element_size) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -869,7 +887,7 @@ int WebMListParser::ParseListElement(int header_size,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMListParser::OnListStart(int id, int64 size) {
|
bool WebMListParser::OnListStart(int id, int64_t size) {
|
||||||
const ListElementInfo* element_info = FindListInfo(id);
|
const ListElementInfo* element_info = FindListInfo(id);
|
||||||
if (!element_info)
|
if (!element_info)
|
||||||
return false;
|
return false;
|
||||||
|
@ -907,7 +925,7 @@ bool WebMListParser::OnListEnd() {
|
||||||
int lists_ended = 0;
|
int lists_ended = 0;
|
||||||
for (; !list_state_stack_.empty(); ++lists_ended) {
|
for (; !list_state_stack_.empty(); ++lists_ended) {
|
||||||
const ListState& list_state = list_state_stack_.back();
|
const ListState& list_state = list_state_stack_.back();
|
||||||
int64 bytes_parsed = list_state.bytes_parsed_;
|
int64_t bytes_parsed = list_state.bytes_parsed_;
|
||||||
int id = list_state.id_;
|
int id = list_state.id_;
|
||||||
|
|
||||||
if (bytes_parsed != list_state.size_)
|
if (bytes_parsed != list_state.size_)
|
||||||
|
@ -952,3 +970,4 @@ bool WebMListParser::IsSiblingOrAncestor(int id_a, int id_b) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -5,12 +5,14 @@
|
||||||
#ifndef MEDIA_FORMATS_WEBM_WEBM_PARSER_H_
|
#ifndef MEDIA_FORMATS_WEBM_WEBM_PARSER_H_
|
||||||
#define MEDIA_FORMATS_WEBM_WEBM_PARSER_H_
|
#define MEDIA_FORMATS_WEBM_WEBM_PARSER_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "packager/base/macros.h"
|
||||||
#include "media/base/media_export.h"
|
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
// Interface for receiving WebM parser events.
|
// Interface for receiving WebM parser events.
|
||||||
|
@ -25,15 +27,15 @@ namespace media {
|
||||||
// handle elements parsed out of the list being started. If false (or NULL by
|
// handle elements parsed out of the list being started. If false (or NULL by
|
||||||
// OnListStart) is returned then the parse is immediately terminated and an
|
// OnListStart) is returned then the parse is immediately terminated and an
|
||||||
// error is reported by the parser.
|
// error is reported by the parser.
|
||||||
class MEDIA_EXPORT WebMParserClient {
|
class WebMParserClient {
|
||||||
public:
|
public:
|
||||||
virtual ~WebMParserClient();
|
virtual ~WebMParserClient();
|
||||||
|
|
||||||
virtual WebMParserClient* OnListStart(int id);
|
virtual WebMParserClient* OnListStart(int id);
|
||||||
virtual bool OnListEnd(int id);
|
virtual bool OnListEnd(int id);
|
||||||
virtual bool OnUInt(int id, int64 val);
|
virtual bool OnUInt(int id, int64_t val);
|
||||||
virtual bool OnFloat(int id, double val);
|
virtual bool OnFloat(int id, double val);
|
||||||
virtual bool OnBinary(int id, const uint8* data, int size);
|
virtual bool OnBinary(int id, const uint8_t* data, int size);
|
||||||
virtual bool OnString(int id, const std::string& str);
|
virtual bool OnString(int id, const std::string& str);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -49,7 +51,7 @@ struct ListElementInfo;
|
||||||
// can be called multiple times with pieces of the list.
|
// can be called multiple times with pieces of the list.
|
||||||
// IsParsingComplete() will return true once the entire list has
|
// IsParsingComplete() will return true once the entire list has
|
||||||
// been parsed.
|
// been parsed.
|
||||||
class MEDIA_EXPORT WebMListParser {
|
class WebMListParser {
|
||||||
public:
|
public:
|
||||||
// |id| - Element ID of the list we intend to parse.
|
// |id| - Element ID of the list we intend to parse.
|
||||||
// |client| - Called as different elements in the list are parsed.
|
// |client| - Called as different elements in the list are parsed.
|
||||||
|
@ -64,7 +66,7 @@ class MEDIA_EXPORT WebMListParser {
|
||||||
// Returns < 0 if the parse fails.
|
// Returns < 0 if the parse fails.
|
||||||
// Returns 0 if more data is needed.
|
// Returns 0 if more data is needed.
|
||||||
// Returning > 0 indicates success & the number of bytes parsed.
|
// Returning > 0 indicates success & the number of bytes parsed.
|
||||||
int Parse(const uint8* buf, int size);
|
int Parse(const uint8_t* buf, int size);
|
||||||
|
|
||||||
// Returns true if the entire list has been parsed.
|
// Returns true if the entire list has been parsed.
|
||||||
bool IsParsingComplete() const;
|
bool IsParsingComplete() const;
|
||||||
|
@ -79,8 +81,8 @@ class MEDIA_EXPORT WebMListParser {
|
||||||
|
|
||||||
struct ListState {
|
struct ListState {
|
||||||
int id_;
|
int id_;
|
||||||
int64 size_;
|
int64_t size_;
|
||||||
int64 bytes_parsed_;
|
int64_t bytes_parsed_;
|
||||||
const ListElementInfo* element_info_;
|
const ListElementInfo* element_info_;
|
||||||
WebMParserClient* client_;
|
WebMParserClient* client_;
|
||||||
};
|
};
|
||||||
|
@ -100,8 +102,10 @@ class MEDIA_EXPORT WebMListParser {
|
||||||
// Returns 0 if more data is needed.
|
// Returns 0 if more data is needed.
|
||||||
// Returning > 0 indicates success & the number of bytes parsed.
|
// Returning > 0 indicates success & the number of bytes parsed.
|
||||||
int ParseListElement(int header_size,
|
int ParseListElement(int header_size,
|
||||||
int id, int64 element_size,
|
int id,
|
||||||
const uint8* data, int size);
|
int64_t element_size,
|
||||||
|
const uint8_t* data,
|
||||||
|
int size);
|
||||||
|
|
||||||
// Called when starting to parse a new list.
|
// Called when starting to parse a new list.
|
||||||
//
|
//
|
||||||
|
@ -111,7 +115,7 @@ class MEDIA_EXPORT WebMListParser {
|
||||||
//
|
//
|
||||||
// Returns true if this list can be started in the current context. False
|
// Returns true if this list can be started in the current context. False
|
||||||
// if starting this list causes some sort of parse error.
|
// if starting this list causes some sort of parse error.
|
||||||
bool OnListStart(int id, int64 size);
|
bool OnListStart(int id, int64_t size);
|
||||||
|
|
||||||
// Called when the end of the current list has been reached. This may also
|
// Called when the end of the current list has been reached. This may also
|
||||||
// signal the end of the current list's ancestors if the current list happens
|
// signal the end of the current list's ancestors if the current list happens
|
||||||
|
@ -150,9 +154,12 @@ class MEDIA_EXPORT WebMListParser {
|
||||||
// |*id| contains the element ID on success and is undefined otherwise.
|
// |*id| contains the element ID on success and is undefined otherwise.
|
||||||
// |*element_size| contains the element size on success and is undefined
|
// |*element_size| contains the element size on success and is undefined
|
||||||
// otherwise.
|
// otherwise.
|
||||||
int MEDIA_EXPORT WebMParseElementHeader(const uint8* buf, int size,
|
int WebMParseElementHeader(const uint8_t* buf,
|
||||||
int* id, int64* element_size);
|
int size,
|
||||||
|
int* id,
|
||||||
|
int64_t* element_size);
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_WEBM_PARSER_H_
|
#endif // MEDIA_FORMATS_WEBM_WEBM_PARSER_H_
|
||||||
|
|
|
@ -2,11 +2,13 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/cluster_builder.h"
|
#include "packager/media/formats/webm/webm_parser.h"
|
||||||
#include "media/formats/webm/webm_constants.h"
|
|
||||||
#include "media/formats/webm/webm_parser.h"
|
#include <gmock/gmock.h>
|
||||||
#include "testing/gmock/include/gmock/gmock.h"
|
#include <gtest/gtest.h>
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
|
||||||
|
#include "packager/media/formats/webm/cluster_builder.h"
|
||||||
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
using ::testing::InSequence;
|
using ::testing::InSequence;
|
||||||
using ::testing::Return;
|
using ::testing::Return;
|
||||||
|
@ -14,6 +16,7 @@ using ::testing::ReturnNull;
|
||||||
using ::testing::StrictMock;
|
using ::testing::StrictMock;
|
||||||
using ::testing::_;
|
using ::testing::_;
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
enum { kBlockCount = 5 };
|
enum { kBlockCount = 5 };
|
||||||
|
@ -25,9 +28,9 @@ class MockWebMParserClient : public WebMParserClient {
|
||||||
// WebMParserClient methods.
|
// WebMParserClient methods.
|
||||||
MOCK_METHOD1(OnListStart, WebMParserClient*(int));
|
MOCK_METHOD1(OnListStart, WebMParserClient*(int));
|
||||||
MOCK_METHOD1(OnListEnd, bool(int));
|
MOCK_METHOD1(OnListEnd, bool(int));
|
||||||
MOCK_METHOD2(OnUInt, bool(int, int64));
|
MOCK_METHOD2(OnUInt, bool(int, int64_t));
|
||||||
MOCK_METHOD2(OnFloat, bool(int, double));
|
MOCK_METHOD2(OnFloat, bool(int, double));
|
||||||
MOCK_METHOD3(OnBinary, bool(int, const uint8*, int));
|
MOCK_METHOD3(OnBinary, bool(int, const uint8_t*, int));
|
||||||
MOCK_METHOD2(OnString, bool(int, const std::string&));
|
MOCK_METHOD2(OnString, bool(int, const std::string&));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,7 +44,7 @@ static scoped_ptr<Cluster> CreateCluster(int block_count) {
|
||||||
cb.SetClusterTimecode(0);
|
cb.SetClusterTimecode(0);
|
||||||
|
|
||||||
for (int i = 0; i < block_count; i++) {
|
for (int i = 0; i < block_count; i++) {
|
||||||
uint8 data[] = { 0x00 };
|
uint8_t data[] = {0x00};
|
||||||
cb.AddSimpleBlock(0, i, 0, data, sizeof(data));
|
cb.AddSimpleBlock(0, i, 0, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,8 +70,8 @@ static void CreateClusterExpectations(int block_count,
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMParserTest, EmptyCluster) {
|
TEST_F(WebMParserTest, EmptyCluster) {
|
||||||
const uint8 kEmptyCluster[] = {
|
const uint8_t kEmptyCluster[] = {
|
||||||
0x1F, 0x43, 0xB6, 0x75, 0x80 // CLUSTER (size = 0)
|
0x1F, 0x43, 0xB6, 0x75, 0x80 // CLUSTER (size = 0)
|
||||||
};
|
};
|
||||||
int size = sizeof(kEmptyCluster);
|
int size = sizeof(kEmptyCluster);
|
||||||
|
|
||||||
|
@ -82,9 +85,9 @@ TEST_F(WebMParserTest, EmptyCluster) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMParserTest, EmptyClusterInSegment) {
|
TEST_F(WebMParserTest, EmptyClusterInSegment) {
|
||||||
const uint8 kBuffer[] = {
|
const uint8_t kBuffer[] = {
|
||||||
0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 5)
|
0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 5)
|
||||||
0x1F, 0x43, 0xB6, 0x75, 0x80, // CLUSTER (size = 0)
|
0x1F, 0x43, 0xB6, 0x75, 0x80, // CLUSTER (size = 0)
|
||||||
};
|
};
|
||||||
int size = sizeof(kBuffer);
|
int size = sizeof(kBuffer);
|
||||||
|
|
||||||
|
@ -102,9 +105,9 @@ TEST_F(WebMParserTest, EmptyClusterInSegment) {
|
||||||
// Test the case where a non-list child element has a size
|
// Test the case where a non-list child element has a size
|
||||||
// that is beyond the end of the parent.
|
// that is beyond the end of the parent.
|
||||||
TEST_F(WebMParserTest, ChildNonListLargerThanParent) {
|
TEST_F(WebMParserTest, ChildNonListLargerThanParent) {
|
||||||
const uint8 kBuffer[] = {
|
const uint8_t kBuffer[] = {
|
||||||
0x1F, 0x43, 0xB6, 0x75, 0x81, // CLUSTER (size = 1)
|
0x1F, 0x43, 0xB6, 0x75, 0x81, // CLUSTER (size = 1)
|
||||||
0xE7, 0x81, 0x01, // Timecode (size=1, value=1)
|
0xE7, 0x81, 0x01, // Timecode (size=1, value=1)
|
||||||
};
|
};
|
||||||
|
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
@ -118,9 +121,9 @@ TEST_F(WebMParserTest, ChildNonListLargerThanParent) {
|
||||||
// Test the case where a list child element has a size
|
// Test the case where a list child element has a size
|
||||||
// that is beyond the end of the parent.
|
// that is beyond the end of the parent.
|
||||||
TEST_F(WebMParserTest, ChildListLargerThanParent) {
|
TEST_F(WebMParserTest, ChildListLargerThanParent) {
|
||||||
const uint8 kBuffer[] = {
|
const uint8_t kBuffer[] = {
|
||||||
0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 5)
|
0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 5)
|
||||||
0x1F, 0x43, 0xB6, 0x75, 0x81, 0x11 // CLUSTER (size = 1)
|
0x1F, 0x43, 0xB6, 0x75, 0x81, 0x11 // CLUSTER (size = 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
@ -133,8 +136,8 @@ TEST_F(WebMParserTest, ChildListLargerThanParent) {
|
||||||
|
|
||||||
// Expecting to parse a Cluster, but get a Segment.
|
// Expecting to parse a Cluster, but get a Segment.
|
||||||
TEST_F(WebMParserTest, ListIdDoesNotMatch) {
|
TEST_F(WebMParserTest, ListIdDoesNotMatch) {
|
||||||
const uint8 kBuffer[] = {
|
const uint8_t kBuffer[] = {
|
||||||
0x18, 0x53, 0x80, 0x67, 0x80, // SEGMENT (size = 0)
|
0x18, 0x53, 0x80, 0x67, 0x80, // SEGMENT (size = 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
WebMListParser parser(kWebMIdCluster, &client_);
|
WebMListParser parser(kWebMIdCluster, &client_);
|
||||||
|
@ -143,9 +146,9 @@ TEST_F(WebMParserTest, ListIdDoesNotMatch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMParserTest, InvalidElementInList) {
|
TEST_F(WebMParserTest, InvalidElementInList) {
|
||||||
const uint8 kBuffer[] = {
|
const uint8_t kBuffer[] = {
|
||||||
0x18, 0x53, 0x80, 0x67, 0x82, // SEGMENT (size = 2)
|
0x18, 0x53, 0x80, 0x67, 0x82, // SEGMENT (size = 2)
|
||||||
0xAE, 0x80, // TrackEntry (size = 0)
|
0xAE, 0x80, // TrackEntry (size = 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
@ -159,9 +162,9 @@ TEST_F(WebMParserTest, InvalidElementInList) {
|
||||||
// Test specific case of InvalidElementInList to verify EBMLHEADER within
|
// Test specific case of InvalidElementInList to verify EBMLHEADER within
|
||||||
// known-sized cluster causes parse error.
|
// known-sized cluster causes parse error.
|
||||||
TEST_F(WebMParserTest, InvalidEBMLHeaderInCluster) {
|
TEST_F(WebMParserTest, InvalidEBMLHeaderInCluster) {
|
||||||
const uint8 kBuffer[] = {
|
const uint8_t kBuffer[] = {
|
||||||
0x1F, 0x43, 0xB6, 0x75, 0x85, // CLUSTER (size = 5)
|
0x1F, 0x43, 0xB6, 0x75, 0x85, // CLUSTER (size = 5)
|
||||||
0x1A, 0x45, 0xDF, 0xA3, 0x80, // EBMLHEADER (size = 0)
|
0x1A, 0x45, 0xDF, 0xA3, 0x80, // EBMLHEADER (size = 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
@ -174,9 +177,11 @@ TEST_F(WebMParserTest, InvalidEBMLHeaderInCluster) {
|
||||||
|
|
||||||
// Verify that EBMLHEADER ends a preceding "unknown"-sized CLUSTER.
|
// Verify that EBMLHEADER ends a preceding "unknown"-sized CLUSTER.
|
||||||
TEST_F(WebMParserTest, UnknownSizeClusterFollowedByEBMLHeader) {
|
TEST_F(WebMParserTest, UnknownSizeClusterFollowedByEBMLHeader) {
|
||||||
const uint8 kBuffer[] = {
|
const uint8_t kBuffer[] = {
|
||||||
0x1F, 0x43, 0xB6, 0x75, 0xFF, // CLUSTER (size = unknown; really 0 due to:)
|
0x1F, 0x43, 0xB6,
|
||||||
0x1A, 0x45, 0xDF, 0xA3, 0x80, // EBMLHEADER (size = 0)
|
0x75, 0xFF, // CLUSTER (size = unknown; really 0 due to:)
|
||||||
|
0x1A, 0x45, 0xDF,
|
||||||
|
0xA3, 0x80, // EBMLHEADER (size = 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
@ -191,13 +196,13 @@ TEST_F(WebMParserTest, UnknownSizeClusterFollowedByEBMLHeader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMParserTest, VoidAndCRC32InList) {
|
TEST_F(WebMParserTest, VoidAndCRC32InList) {
|
||||||
const uint8 kBuffer[] = {
|
const uint8_t kBuffer[] = {
|
||||||
0x18, 0x53, 0x80, 0x67, 0x99, // SEGMENT (size = 25)
|
0x18, 0x53, 0x80, 0x67, 0x99, // SEGMENT (size = 25)
|
||||||
0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3)
|
0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3)
|
||||||
0xBF, 0x83, 0x00, 0x00, 0x00, // CRC32 (size = 3)
|
0xBF, 0x83, 0x00, 0x00, 0x00, // CRC32 (size = 3)
|
||||||
0x1F, 0x43, 0xB6, 0x75, 0x8A, // CLUSTER (size = 10)
|
0x1F, 0x43, 0xB6, 0x75, 0x8A, // CLUSTER (size = 10)
|
||||||
0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3)
|
0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3)
|
||||||
0xBF, 0x83, 0x00, 0x00, 0x00, // CRC32 (size = 3)
|
0xBF, 0x83, 0x00, 0x00, 0x00, // CRC32 (size = 3)
|
||||||
};
|
};
|
||||||
int size = sizeof(kBuffer);
|
int size = sizeof(kBuffer);
|
||||||
|
|
||||||
|
@ -226,7 +231,7 @@ TEST_F(WebMParserTest, ParseListElementWithMultipleCalls) {
|
||||||
scoped_ptr<Cluster> cluster(CreateCluster(kBlockCount));
|
scoped_ptr<Cluster> cluster(CreateCluster(kBlockCount));
|
||||||
CreateClusterExpectations(kBlockCount, true, &client_);
|
CreateClusterExpectations(kBlockCount, true, &client_);
|
||||||
|
|
||||||
const uint8* data = cluster->data();
|
const uint8_t* data = cluster->data();
|
||||||
int size = cluster->size();
|
int size = cluster->size();
|
||||||
int default_parse_size = 3;
|
int default_parse_size = 3;
|
||||||
WebMListParser parser(kWebMIdCluster, &client_);
|
WebMListParser parser(kWebMIdCluster, &client_);
|
||||||
|
@ -283,13 +288,13 @@ TEST_F(WebMParserTest, Reset) {
|
||||||
|
|
||||||
// Test the case where multiple clients are used for different lists.
|
// Test the case where multiple clients are used for different lists.
|
||||||
TEST_F(WebMParserTest, MultipleClients) {
|
TEST_F(WebMParserTest, MultipleClients) {
|
||||||
const uint8 kBuffer[] = {
|
const uint8_t kBuffer[] = {
|
||||||
0x18, 0x53, 0x80, 0x67, 0x94, // SEGMENT (size = 20)
|
0x18, 0x53, 0x80, 0x67, 0x94, // SEGMENT (size = 20)
|
||||||
0x16, 0x54, 0xAE, 0x6B, 0x85, // TRACKS (size = 5)
|
0x16, 0x54, 0xAE, 0x6B, 0x85, // TRACKS (size = 5)
|
||||||
0xAE, 0x83, // TRACKENTRY (size = 3)
|
0xAE, 0x83, // TRACKENTRY (size = 3)
|
||||||
0xD7, 0x81, 0x01, // TRACKNUMBER (size = 1)
|
0xD7, 0x81, 0x01, // TRACKNUMBER (size = 1)
|
||||||
0x1F, 0x43, 0xB6, 0x75, 0x85, // CLUSTER (size = 5)
|
0x1F, 0x43, 0xB6, 0x75, 0x85, // CLUSTER (size = 5)
|
||||||
0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3)
|
0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3)
|
||||||
};
|
};
|
||||||
int size = sizeof(kBuffer);
|
int size = sizeof(kBuffer);
|
||||||
|
|
||||||
|
@ -315,9 +320,9 @@ TEST_F(WebMParserTest, MultipleClients) {
|
||||||
|
|
||||||
// Test the case where multiple clients are used for different lists.
|
// Test the case where multiple clients are used for different lists.
|
||||||
TEST_F(WebMParserTest, InvalidClient) {
|
TEST_F(WebMParserTest, InvalidClient) {
|
||||||
const uint8 kBuffer[] = {
|
const uint8_t kBuffer[] = {
|
||||||
0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 20)
|
0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 20)
|
||||||
0x16, 0x54, 0xAE, 0x6B, 0x80, // TRACKS (size = 5)
|
0x16, 0x54, 0xAE, 0x6B, 0x80, // TRACKS (size = 5)
|
||||||
};
|
};
|
||||||
|
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
@ -329,20 +334,16 @@ TEST_F(WebMParserTest, InvalidClient) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMParserTest, ReservedIds) {
|
TEST_F(WebMParserTest, ReservedIds) {
|
||||||
const uint8 k1ByteReservedId[] = { 0xFF, 0x81 };
|
const uint8_t k1ByteReservedId[] = {0xFF, 0x81};
|
||||||
const uint8 k2ByteReservedId[] = { 0x7F, 0xFF, 0x81 };
|
const uint8_t k2ByteReservedId[] = {0x7F, 0xFF, 0x81};
|
||||||
const uint8 k3ByteReservedId[] = { 0x3F, 0xFF, 0xFF, 0x81 };
|
const uint8_t k3ByteReservedId[] = {0x3F, 0xFF, 0xFF, 0x81};
|
||||||
const uint8 k4ByteReservedId[] = { 0x1F, 0xFF, 0xFF, 0xFF, 0x81 };
|
const uint8_t k4ByteReservedId[] = {0x1F, 0xFF, 0xFF, 0xFF, 0x81};
|
||||||
const uint8* kBuffers[] = {
|
const uint8_t* kBuffers[] = {k1ByteReservedId, k2ByteReservedId,
|
||||||
k1ByteReservedId,
|
k3ByteReservedId, k4ByteReservedId};
|
||||||
k2ByteReservedId,
|
|
||||||
k3ByteReservedId,
|
|
||||||
k4ByteReservedId
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < arraysize(kBuffers); i++) {
|
for (size_t i = 0; i < arraysize(kBuffers); i++) {
|
||||||
int id;
|
int id;
|
||||||
int64 element_size;
|
int64_t element_size;
|
||||||
int buffer_size = 2 + i;
|
int buffer_size = 2 + i;
|
||||||
EXPECT_EQ(buffer_size, WebMParseElementHeader(kBuffers[i], buffer_size,
|
EXPECT_EQ(buffer_size, WebMParseElementHeader(kBuffers[i], buffer_size,
|
||||||
&id, &element_size));
|
&id, &element_size));
|
||||||
|
@ -352,31 +353,25 @@ TEST_F(WebMParserTest, ReservedIds) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMParserTest, ReservedSizes) {
|
TEST_F(WebMParserTest, ReservedSizes) {
|
||||||
const uint8 k1ByteReservedSize[] = { 0xA3, 0xFF };
|
const uint8_t k1ByteReservedSize[] = {0xA3, 0xFF};
|
||||||
const uint8 k2ByteReservedSize[] = { 0xA3, 0x7F, 0xFF };
|
const uint8_t k2ByteReservedSize[] = {0xA3, 0x7F, 0xFF};
|
||||||
const uint8 k3ByteReservedSize[] = { 0xA3, 0x3F, 0xFF, 0xFF };
|
const uint8_t k3ByteReservedSize[] = {0xA3, 0x3F, 0xFF, 0xFF};
|
||||||
const uint8 k4ByteReservedSize[] = { 0xA3, 0x1F, 0xFF, 0xFF, 0xFF };
|
const uint8_t k4ByteReservedSize[] = {0xA3, 0x1F, 0xFF, 0xFF, 0xFF};
|
||||||
const uint8 k5ByteReservedSize[] = { 0xA3, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF };
|
const uint8_t k5ByteReservedSize[] = {0xA3, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||||
const uint8 k6ByteReservedSize[] = { 0xA3, 0x07, 0xFF, 0xFF, 0xFF, 0xFF,
|
const uint8_t k6ByteReservedSize[] = {0xA3, 0x07, 0xFF, 0xFF,
|
||||||
0xFF };
|
0xFF, 0xFF, 0xFF};
|
||||||
const uint8 k7ByteReservedSize[] = { 0xA3, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
const uint8_t k7ByteReservedSize[] = {0xA3, 0x03, 0xFF, 0xFF,
|
||||||
0xFF };
|
0xFF, 0xFF, 0xFF, 0xFF};
|
||||||
const uint8 k8ByteReservedSize[] = { 0xA3, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
const uint8_t k8ByteReservedSize[] = {0xA3, 0x01, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF };
|
0xFF, 0xFF, 0xFF, 0xFF};
|
||||||
const uint8* kBuffers[] = {
|
const uint8_t* kBuffers[] = {k1ByteReservedSize, k2ByteReservedSize,
|
||||||
k1ByteReservedSize,
|
k3ByteReservedSize, k4ByteReservedSize,
|
||||||
k2ByteReservedSize,
|
k5ByteReservedSize, k6ByteReservedSize,
|
||||||
k3ByteReservedSize,
|
k7ByteReservedSize, k8ByteReservedSize};
|
||||||
k4ByteReservedSize,
|
|
||||||
k5ByteReservedSize,
|
|
||||||
k6ByteReservedSize,
|
|
||||||
k7ByteReservedSize,
|
|
||||||
k8ByteReservedSize
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < arraysize(kBuffers); i++) {
|
for (size_t i = 0; i < arraysize(kBuffers); i++) {
|
||||||
int id;
|
int id;
|
||||||
int64 element_size;
|
int64_t element_size;
|
||||||
int buffer_size = 2 + i;
|
int buffer_size = 2 + i;
|
||||||
EXPECT_EQ(buffer_size, WebMParseElementHeader(kBuffers[i], buffer_size,
|
EXPECT_EQ(buffer_size, WebMParseElementHeader(kBuffers[i], buffer_size,
|
||||||
&id, &element_size));
|
&id, &element_size));
|
||||||
|
@ -386,12 +381,12 @@ TEST_F(WebMParserTest, ReservedSizes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMParserTest, ZeroPaddedStrings) {
|
TEST_F(WebMParserTest, ZeroPaddedStrings) {
|
||||||
const uint8 kBuffer[] = {
|
const uint8_t kBuffer[] = {
|
||||||
0x1A, 0x45, 0xDF, 0xA3, 0x91, // EBMLHEADER (size = 17)
|
0x1A, 0x45, 0xDF, 0xA3, 0x91, // EBMLHEADER (size = 17)
|
||||||
0x42, 0x82, 0x80, // DocType (size = 0)
|
0x42, 0x82, 0x80, // DocType (size = 0)
|
||||||
0x42, 0x82, 0x81, 0x00, // DocType (size = 1) ""
|
0x42, 0x82, 0x81, 0x00, // DocType (size = 1) ""
|
||||||
0x42, 0x82, 0x81, 'a', // DocType (size = 1) "a"
|
0x42, 0x82, 0x81, 'a', // DocType (size = 1) "a"
|
||||||
0x42, 0x82, 0x83, 'a', 0x00, 0x00 // DocType (size = 3) "a"
|
0x42, 0x82, 0x83, 'a', 0x00, 0x00 // DocType (size = 3) "a"
|
||||||
};
|
};
|
||||||
int size = sizeof(kBuffer);
|
int size = sizeof(kBuffer);
|
||||||
|
|
||||||
|
@ -410,3 +405,4 @@ TEST_F(WebMParserTest, ZeroPaddedStrings) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -2,20 +2,21 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/webm_stream_parser.h"
|
#include "packager/media/formats/webm/webm_stream_parser.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "base/callback.h"
|
#include "packager/base/callback.h"
|
||||||
#include "base/callback_helpers.h"
|
#include "packager/base/callback_helpers.h"
|
||||||
#include "base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "media/base/timestamp_constants.h"
|
#include "packager/media/base/timestamp_constants.h"
|
||||||
#include "media/formats/webm/webm_cluster_parser.h"
|
#include "packager/media/formats/webm/webm_cluster_parser.h"
|
||||||
#include "media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
#include "media/formats/webm/webm_content_encodings.h"
|
#include "packager/media/formats/webm/webm_content_encodings.h"
|
||||||
#include "media/formats/webm/webm_info_parser.h"
|
#include "packager/media/formats/webm/webm_info_parser.h"
|
||||||
#include "media/formats/webm/webm_tracks_parser.h"
|
#include "packager/media/formats/webm/webm_tracks_parser.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
WebMStreamParser::WebMStreamParser()
|
WebMStreamParser::WebMStreamParser()
|
||||||
|
@ -33,8 +34,7 @@ void WebMStreamParser::Init(
|
||||||
bool ignore_text_tracks,
|
bool ignore_text_tracks,
|
||||||
const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
|
const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
|
||||||
const NewMediaSegmentCB& new_segment_cb,
|
const NewMediaSegmentCB& new_segment_cb,
|
||||||
const base::Closure& end_of_segment_cb,
|
const base::Closure& end_of_segment_cb) {
|
||||||
const scoped_refptr<MediaLog>& media_log) {
|
|
||||||
DCHECK_EQ(state_, kWaitingForInit);
|
DCHECK_EQ(state_, kWaitingForInit);
|
||||||
DCHECK(init_cb_.is_null());
|
DCHECK(init_cb_.is_null());
|
||||||
DCHECK(!init_cb.is_null());
|
DCHECK(!init_cb.is_null());
|
||||||
|
@ -52,7 +52,6 @@ void WebMStreamParser::Init(
|
||||||
encrypted_media_init_data_cb_ = encrypted_media_init_data_cb;
|
encrypted_media_init_data_cb_ = encrypted_media_init_data_cb;
|
||||||
new_segment_cb_ = new_segment_cb;
|
new_segment_cb_ = new_segment_cb;
|
||||||
end_of_segment_cb_ = end_of_segment_cb;
|
end_of_segment_cb_ = end_of_segment_cb;
|
||||||
media_log_ = media_log;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebMStreamParser::Flush() {
|
void WebMStreamParser::Flush() {
|
||||||
|
@ -67,7 +66,7 @@ void WebMStreamParser::Flush() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMStreamParser::Parse(const uint8* buf, int size) {
|
bool WebMStreamParser::Parse(const uint8_t* buf, int size) {
|
||||||
DCHECK_NE(state_, kWaitingForInit);
|
DCHECK_NE(state_, kWaitingForInit);
|
||||||
|
|
||||||
if (state_ == kError)
|
if (state_ == kError)
|
||||||
|
@ -77,7 +76,7 @@ bool WebMStreamParser::Parse(const uint8* buf, int size) {
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
int bytes_parsed = 0;
|
int bytes_parsed = 0;
|
||||||
const uint8* cur = NULL;
|
const uint8_t* cur = NULL;
|
||||||
int cur_size = 0;
|
int cur_size = 0;
|
||||||
|
|
||||||
byte_queue_.Peek(&cur, &cur_size);
|
byte_queue_.Peek(&cur, &cur_size);
|
||||||
|
@ -120,17 +119,17 @@ void WebMStreamParser::ChangeState(State new_state) {
|
||||||
state_ = new_state;
|
state_ = new_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) {
|
int WebMStreamParser::ParseInfoAndTracks(const uint8_t* data, int size) {
|
||||||
DVLOG(2) << "ParseInfoAndTracks()";
|
DVLOG(2) << "ParseInfoAndTracks()";
|
||||||
DCHECK(data);
|
DCHECK(data);
|
||||||
DCHECK_GT(size, 0);
|
DCHECK_GT(size, 0);
|
||||||
|
|
||||||
const uint8* cur = data;
|
const uint8_t* cur = data;
|
||||||
int cur_size = size;
|
int cur_size = size;
|
||||||
int bytes_parsed = 0;
|
int bytes_parsed = 0;
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
int64 element_size;
|
int64_t element_size;
|
||||||
int result = WebMParseElementHeader(cur, cur_size, &id, &element_size);
|
int result = WebMParseElementHeader(cur, cur_size, &id, &element_size);
|
||||||
|
|
||||||
if (result <= 0)
|
if (result <= 0)
|
||||||
|
@ -155,7 +154,7 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) {
|
||||||
break;
|
break;
|
||||||
case kWebMIdCluster:
|
case kWebMIdCluster:
|
||||||
if (!cluster_parser_) {
|
if (!cluster_parser_) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Found Cluster element before Info.";
|
LOG(ERROR) << "Found Cluster element before Info.";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ChangeState(kParsingClusters);
|
ChangeState(kParsingClusters);
|
||||||
|
@ -173,8 +172,7 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) {
|
||||||
// We've found the element we are looking for.
|
// We've found the element we are looking for.
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unexpected element ID 0x" << std::hex
|
LOG(ERROR) << "Unexpected element ID 0x" << std::hex << id;
|
||||||
<< id;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,7 +187,7 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) {
|
||||||
cur_size -= result;
|
cur_size -= result;
|
||||||
bytes_parsed += result;
|
bytes_parsed += result;
|
||||||
|
|
||||||
WebMTracksParser tracks_parser(media_log_, ignore_text_tracks_);
|
WebMTracksParser tracks_parser(ignore_text_tracks_);
|
||||||
result = tracks_parser.Parse(cur, cur_size);
|
result = tracks_parser.Parse(cur, cur_size);
|
||||||
|
|
||||||
if (result <= 0)
|
if (result <= 0)
|
||||||
|
@ -201,7 +199,7 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) {
|
||||||
InitParameters params(kInfiniteDuration());
|
InitParameters params(kInfiniteDuration());
|
||||||
|
|
||||||
if (info_parser.duration() > 0) {
|
if (info_parser.duration() > 0) {
|
||||||
int64 duration_in_us = info_parser.duration() * timecode_scale_in_us;
|
int64_t duration_in_us = info_parser.duration() * timecode_scale_in_us;
|
||||||
params.duration = base::TimeDelta::FromMicroseconds(duration_in_us);
|
params.duration = base::TimeDelta::FromMicroseconds(duration_in_us);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,8 +236,7 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) {
|
||||||
tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us),
|
tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us),
|
||||||
tracks_parser.text_tracks(), tracks_parser.ignored_tracks(),
|
tracks_parser.text_tracks(), tracks_parser.ignored_tracks(),
|
||||||
tracks_parser.audio_encryption_key_id(),
|
tracks_parser.audio_encryption_key_id(),
|
||||||
tracks_parser.video_encryption_key_id(), audio_config.codec(),
|
tracks_parser.video_encryption_key_id(), audio_config.codec());
|
||||||
media_log_));
|
|
||||||
|
|
||||||
if (!init_cb_.is_null())
|
if (!init_cb_.is_null())
|
||||||
base::ResetAndReturn(&init_cb_).Run(params);
|
base::ResetAndReturn(&init_cb_).Run(params);
|
||||||
|
@ -247,7 +244,7 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) {
|
||||||
return bytes_parsed;
|
return bytes_parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WebMStreamParser::ParseCluster(const uint8* data, int size) {
|
int WebMStreamParser::ParseCluster(const uint8_t* data, int size) {
|
||||||
if (!cluster_parser_)
|
if (!cluster_parser_)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -276,8 +273,9 @@ int WebMStreamParser::ParseCluster(const uint8* data, int size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebMStreamParser::OnEncryptedMediaInitData(const std::string& key_id) {
|
void WebMStreamParser::OnEncryptedMediaInitData(const std::string& key_id) {
|
||||||
std::vector<uint8> key_id_vector(key_id.begin(), key_id.end());
|
std::vector<uint8_t> key_id_vector(key_id.begin(), key_id.end());
|
||||||
encrypted_media_init_data_cb_.Run(EmeInitDataType::WEBM, key_id_vector);
|
encrypted_media_init_data_cb_.Run(EmeInitDataType::WEBM, key_id_vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -5,13 +5,14 @@
|
||||||
#ifndef MEDIA_FORMATS_WEBM_WEBM_STREAM_PARSER_H_
|
#ifndef MEDIA_FORMATS_WEBM_WEBM_STREAM_PARSER_H_
|
||||||
#define MEDIA_FORMATS_WEBM_WEBM_STREAM_PARSER_H_
|
#define MEDIA_FORMATS_WEBM_WEBM_STREAM_PARSER_H_
|
||||||
|
|
||||||
#include "base/callback_forward.h"
|
#include "packager/base/callback_forward.h"
|
||||||
#include "base/memory/ref_counted.h"
|
#include "packager/base/memory/ref_counted.h"
|
||||||
#include "media/base/audio_decoder_config.h"
|
#include "packager/media/base/audio_decoder_config.h"
|
||||||
#include "media/base/byte_queue.h"
|
#include "packager/media/base/byte_queue.h"
|
||||||
#include "media/base/stream_parser.h"
|
#include "packager/media/base/stream_parser.h"
|
||||||
#include "media/base/video_decoder_config.h"
|
#include "packager/media/base/video_decoder_config.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
class WebMClusterParser;
|
class WebMClusterParser;
|
||||||
|
@ -28,10 +29,9 @@ class WebMStreamParser : public StreamParser {
|
||||||
bool ignore_text_tracks,
|
bool ignore_text_tracks,
|
||||||
const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
|
const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
|
||||||
const NewMediaSegmentCB& new_segment_cb,
|
const NewMediaSegmentCB& new_segment_cb,
|
||||||
const base::Closure& end_of_segment_cb,
|
const base::Closure& end_of_segment_cb) override;
|
||||||
const scoped_refptr<MediaLog>& media_log) override;
|
|
||||||
void Flush() override;
|
void Flush() override;
|
||||||
bool Parse(const uint8* buf, int size) override;
|
bool Parse(const uint8_t* buf, int size) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum State {
|
enum State {
|
||||||
|
@ -51,7 +51,7 @@ class WebMStreamParser : public StreamParser {
|
||||||
// Returns < 0 if the parse fails.
|
// Returns < 0 if the parse fails.
|
||||||
// Returns 0 if more data is needed.
|
// Returns 0 if more data is needed.
|
||||||
// Returning > 0 indicates success & the number of bytes parsed.
|
// Returning > 0 indicates success & the number of bytes parsed.
|
||||||
int ParseInfoAndTracks(const uint8* data, int size);
|
int ParseInfoAndTracks(const uint8_t* data, int size);
|
||||||
|
|
||||||
// Incrementally parses WebM cluster elements. This method also skips
|
// Incrementally parses WebM cluster elements. This method also skips
|
||||||
// CUES elements if they are encountered since we currently don't use the
|
// CUES elements if they are encountered since we currently don't use the
|
||||||
|
@ -60,7 +60,7 @@ class WebMStreamParser : public StreamParser {
|
||||||
// Returns < 0 if the parse fails.
|
// Returns < 0 if the parse fails.
|
||||||
// Returns 0 if more data is needed.
|
// Returns 0 if more data is needed.
|
||||||
// Returning > 0 indicates success & the number of bytes parsed.
|
// Returning > 0 indicates success & the number of bytes parsed.
|
||||||
int ParseCluster(const uint8* data, int size);
|
int ParseCluster(const uint8_t* data, int size);
|
||||||
|
|
||||||
// Fire needkey event through the |encrypted_media_init_data_cb_|.
|
// Fire needkey event through the |encrypted_media_init_data_cb_|.
|
||||||
void OnEncryptedMediaInitData(const std::string& key_id);
|
void OnEncryptedMediaInitData(const std::string& key_id);
|
||||||
|
@ -74,7 +74,6 @@ class WebMStreamParser : public StreamParser {
|
||||||
|
|
||||||
NewMediaSegmentCB new_segment_cb_;
|
NewMediaSegmentCB new_segment_cb_;
|
||||||
base::Closure end_of_segment_cb_;
|
base::Closure end_of_segment_cb_;
|
||||||
scoped_refptr<MediaLog> media_log_;
|
|
||||||
|
|
||||||
bool unknown_segment_size_;
|
bool unknown_segment_size_;
|
||||||
|
|
||||||
|
@ -85,5 +84,6 @@ class WebMStreamParser : public StreamParser {
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_WEBM_STREAM_PARSER_H_
|
#endif // MEDIA_FORMATS_WEBM_WEBM_STREAM_PARSER_H_
|
||||||
|
|
|
@ -2,15 +2,16 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/webm_tracks_parser.h"
|
#include "packager/media/formats/webm/webm_tracks_parser.h"
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "base/strings/string_number_conversions.h"
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
#include "base/strings/string_util.h"
|
#include "packager/base/strings/string_util.h"
|
||||||
#include "media/base/timestamp_constants.h"
|
#include "packager/media/base/timestamp_constants.h"
|
||||||
#include "media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
#include "media/formats/webm/webm_content_encodings.h"
|
#include "packager/media/formats/webm/webm_content_encodings.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
static TextKind CodecIdToTextKind(const std::string& codec_id) {
|
static TextKind CodecIdToTextKind(const std::string& codec_id) {
|
||||||
|
@ -30,11 +31,12 @@ static TextKind CodecIdToTextKind(const std::string& codec_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static base::TimeDelta PrecisionCappedDefaultDuration(
|
static base::TimeDelta PrecisionCappedDefaultDuration(
|
||||||
const double timecode_scale_in_us, const int64 duration_in_ns) {
|
const double timecode_scale_in_us,
|
||||||
|
const int64_t duration_in_ns) {
|
||||||
if (duration_in_ns <= 0)
|
if (duration_in_ns <= 0)
|
||||||
return kNoTimestamp();
|
return kNoTimestamp();
|
||||||
|
|
||||||
int64 mult = duration_in_ns / 1000;
|
int64_t mult = duration_in_ns / 1000;
|
||||||
mult /= timecode_scale_in_us;
|
mult /= timecode_scale_in_us;
|
||||||
if (mult == 0)
|
if (mult == 0)
|
||||||
return kNoTimestamp();
|
return kNoTimestamp();
|
||||||
|
@ -43,8 +45,7 @@ static base::TimeDelta PrecisionCappedDefaultDuration(
|
||||||
return base::TimeDelta::FromMicroseconds(mult);
|
return base::TimeDelta::FromMicroseconds(mult);
|
||||||
}
|
}
|
||||||
|
|
||||||
WebMTracksParser::WebMTracksParser(const scoped_refptr<MediaLog>& media_log,
|
WebMTracksParser::WebMTracksParser(bool ignore_text_tracks)
|
||||||
bool ignore_text_tracks)
|
|
||||||
: track_type_(-1),
|
: track_type_(-1),
|
||||||
track_num_(-1),
|
track_num_(-1),
|
||||||
seek_preroll_(-1),
|
seek_preroll_(-1),
|
||||||
|
@ -55,14 +56,13 @@ WebMTracksParser::WebMTracksParser(const scoped_refptr<MediaLog>& media_log,
|
||||||
video_track_num_(-1),
|
video_track_num_(-1),
|
||||||
video_default_duration_(-1),
|
video_default_duration_(-1),
|
||||||
ignore_text_tracks_(ignore_text_tracks),
|
ignore_text_tracks_(ignore_text_tracks),
|
||||||
media_log_(media_log),
|
audio_client_(),
|
||||||
audio_client_(media_log),
|
video_client_() {
|
||||||
video_client_(media_log) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WebMTracksParser::~WebMTracksParser() {}
|
WebMTracksParser::~WebMTracksParser() {}
|
||||||
|
|
||||||
int WebMTracksParser::Parse(const uint8* buf, int size) {
|
int WebMTracksParser::Parse(const uint8_t* buf, int size) {
|
||||||
track_type_ =-1;
|
track_type_ =-1;
|
||||||
track_num_ = -1;
|
track_num_ = -1;
|
||||||
default_duration_ = -1;
|
default_duration_ = -1;
|
||||||
|
@ -102,8 +102,7 @@ base::TimeDelta WebMTracksParser::GetVideoDefaultDuration(
|
||||||
WebMParserClient* WebMTracksParser::OnListStart(int id) {
|
WebMParserClient* WebMTracksParser::OnListStart(int id) {
|
||||||
if (id == kWebMIdContentEncodings) {
|
if (id == kWebMIdContentEncodings) {
|
||||||
DCHECK(!track_content_encodings_client_.get());
|
DCHECK(!track_content_encodings_client_.get());
|
||||||
track_content_encodings_client_.reset(
|
track_content_encodings_client_.reset(new WebMContentEncodingsClient());
|
||||||
new WebMContentEncodingsClient(media_log_));
|
|
||||||
return track_content_encodings_client_->OnListStart(id);
|
return track_content_encodings_client_->OnListStart(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,9 +136,8 @@ bool WebMTracksParser::OnListEnd(int id) {
|
||||||
|
|
||||||
if (id == kWebMIdTrackEntry) {
|
if (id == kWebMIdTrackEntry) {
|
||||||
if (track_type_ == -1 || track_num_ == -1) {
|
if (track_type_ == -1 || track_num_ == -1) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Missing TrackEntry data for "
|
LOG(ERROR) << "Missing TrackEntry data for "
|
||||||
<< " TrackType " << track_type_
|
<< " TrackType " << track_type_ << " TrackNum " << track_num_;
|
||||||
<< " TrackNum " << track_num_;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +145,7 @@ bool WebMTracksParser::OnListEnd(int id) {
|
||||||
track_type_ != kWebMTrackTypeVideo &&
|
track_type_ != kWebMTrackTypeVideo &&
|
||||||
track_type_ != kWebMTrackTypeSubtitlesOrCaptions &&
|
track_type_ != kWebMTrackTypeSubtitlesOrCaptions &&
|
||||||
track_type_ != kWebMTrackTypeDescriptionsOrMetadata) {
|
track_type_ != kWebMTrackTypeDescriptionsOrMetadata) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unexpected TrackType " << track_type_;
|
LOG(ERROR) << "Unexpected TrackType " << track_type_;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,29 +153,29 @@ bool WebMTracksParser::OnListEnd(int id) {
|
||||||
if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions) {
|
if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions) {
|
||||||
text_track_kind = CodecIdToTextKind(codec_id_);
|
text_track_kind = CodecIdToTextKind(codec_id_);
|
||||||
if (text_track_kind == kTextNone) {
|
if (text_track_kind == kTextNone) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Missing TrackEntry CodecID"
|
LOG(ERROR) << "Missing TrackEntry CodecID"
|
||||||
<< " TrackNum " << track_num_;
|
<< " TrackNum " << track_num_;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text_track_kind != kTextSubtitles &&
|
if (text_track_kind != kTextSubtitles &&
|
||||||
text_track_kind != kTextCaptions) {
|
text_track_kind != kTextCaptions) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Wrong TrackEntry CodecID"
|
LOG(ERROR) << "Wrong TrackEntry CodecID"
|
||||||
<< " TrackNum " << track_num_;
|
<< " TrackNum " << track_num_;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (track_type_ == kWebMTrackTypeDescriptionsOrMetadata) {
|
} else if (track_type_ == kWebMTrackTypeDescriptionsOrMetadata) {
|
||||||
text_track_kind = CodecIdToTextKind(codec_id_);
|
text_track_kind = CodecIdToTextKind(codec_id_);
|
||||||
if (text_track_kind == kTextNone) {
|
if (text_track_kind == kTextNone) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Missing TrackEntry CodecID"
|
LOG(ERROR) << "Missing TrackEntry CodecID"
|
||||||
<< " TrackNum " << track_num_;
|
<< " TrackNum " << track_num_;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text_track_kind != kTextDescriptions &&
|
if (text_track_kind != kTextDescriptions &&
|
||||||
text_track_kind != kTextMetadata) {
|
text_track_kind != kTextMetadata) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Wrong TrackEntry CodecID"
|
LOG(ERROR) << "Wrong TrackEntry CodecID"
|
||||||
<< " TrackNum " << track_num_;
|
<< " TrackNum " << track_num_;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,8 +195,8 @@ bool WebMTracksParser::OnListEnd(int id) {
|
||||||
audio_encryption_key_id_ = encryption_key_id;
|
audio_encryption_key_id_ = encryption_key_id;
|
||||||
|
|
||||||
if (default_duration_ == 0) {
|
if (default_duration_ == 0) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Illegal 0ns audio TrackEntry "
|
LOG(ERROR) << "Illegal 0ns audio TrackEntry "
|
||||||
"DefaultDuration";
|
"DefaultDuration";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
audio_default_duration_ = default_duration_;
|
audio_default_duration_ = default_duration_;
|
||||||
|
@ -210,7 +208,7 @@ bool WebMTracksParser::OnListEnd(int id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MEDIA_LOG(DEBUG, media_log_) << "Ignoring audio track " << track_num_;
|
DLOG(INFO) << "Ignoring audio track " << track_num_;
|
||||||
ignored_tracks_.insert(track_num_);
|
ignored_tracks_.insert(track_num_);
|
||||||
}
|
}
|
||||||
} else if (track_type_ == kWebMTrackTypeVideo) {
|
} else if (track_type_ == kWebMTrackTypeVideo) {
|
||||||
|
@ -219,8 +217,8 @@ bool WebMTracksParser::OnListEnd(int id) {
|
||||||
video_encryption_key_id_ = encryption_key_id;
|
video_encryption_key_id_ = encryption_key_id;
|
||||||
|
|
||||||
if (default_duration_ == 0) {
|
if (default_duration_ == 0) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Illegal 0ns video TrackEntry "
|
LOG(ERROR) << "Illegal 0ns video TrackEntry "
|
||||||
"DefaultDuration";
|
"DefaultDuration";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
video_default_duration_ = default_duration_;
|
video_default_duration_ = default_duration_;
|
||||||
|
@ -232,13 +230,13 @@ bool WebMTracksParser::OnListEnd(int id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MEDIA_LOG(DEBUG, media_log_) << "Ignoring video track " << track_num_;
|
DLOG(INFO) << "Ignoring video track " << track_num_;
|
||||||
ignored_tracks_.insert(track_num_);
|
ignored_tracks_.insert(track_num_);
|
||||||
}
|
}
|
||||||
} else if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions ||
|
} else if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions ||
|
||||||
track_type_ == kWebMTrackTypeDescriptionsOrMetadata) {
|
track_type_ == kWebMTrackTypeDescriptionsOrMetadata) {
|
||||||
if (ignore_text_tracks_) {
|
if (ignore_text_tracks_) {
|
||||||
MEDIA_LOG(DEBUG, media_log_) << "Ignoring text track " << track_num_;
|
DLOG(INFO) << "Ignoring text track " << track_num_;
|
||||||
ignored_tracks_.insert(track_num_);
|
ignored_tracks_.insert(track_num_);
|
||||||
} else {
|
} else {
|
||||||
std::string track_num = base::Int64ToString(track_num_);
|
std::string track_num = base::Int64ToString(track_num_);
|
||||||
|
@ -246,7 +244,7 @@ bool WebMTracksParser::OnListEnd(int id) {
|
||||||
text_track_kind, track_name_, track_language_, track_num);
|
text_track_kind, track_name_, track_language_, track_num);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unexpected TrackType " << track_type_;
|
LOG(ERROR) << "Unexpected TrackType " << track_type_;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,8 +265,8 @@ bool WebMTracksParser::OnListEnd(int id) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMTracksParser::OnUInt(int id, int64 val) {
|
bool WebMTracksParser::OnUInt(int id, int64_t val) {
|
||||||
int64* dst = NULL;
|
int64_t* dst = NULL;
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case kWebMIdTrackNumber:
|
case kWebMIdTrackNumber:
|
||||||
|
@ -291,8 +289,7 @@ bool WebMTracksParser::OnUInt(int id, int64 val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*dst != -1) {
|
if (*dst != -1) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Multiple values for id " << std::hex << id
|
LOG(ERROR) << "Multiple values for id " << std::hex << id << " specified";
|
||||||
<< " specified";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,11 +301,10 @@ bool WebMTracksParser::OnFloat(int id, double val) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMTracksParser::OnBinary(int id, const uint8* data, int size) {
|
bool WebMTracksParser::OnBinary(int id, const uint8_t* data, int size) {
|
||||||
if (id == kWebMIdCodecPrivate) {
|
if (id == kWebMIdCodecPrivate) {
|
||||||
if (!codec_private_.empty()) {
|
if (!codec_private_.empty()) {
|
||||||
MEDIA_LOG(ERROR, media_log_)
|
LOG(ERROR) << "Multiple CodecPrivate fields in a track.";
|
||||||
<< "Multiple CodecPrivate fields in a track.";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
codec_private_.assign(data, data + size);
|
codec_private_.assign(data, data + size);
|
||||||
|
@ -320,7 +316,7 @@ bool WebMTracksParser::OnBinary(int id, const uint8* data, int size) {
|
||||||
bool WebMTracksParser::OnString(int id, const std::string& str) {
|
bool WebMTracksParser::OnString(int id, const std::string& str) {
|
||||||
if (id == kWebMIdCodecID) {
|
if (id == kWebMIdCodecID) {
|
||||||
if (!codec_id_.empty()) {
|
if (!codec_id_.empty()) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Multiple CodecID fields in a track";
|
LOG(ERROR) << "Multiple CodecID fields in a track";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,3 +338,4 @@ bool WebMTracksParser::OnString(int id, const std::string& str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -10,25 +10,24 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/compiler_specific.h"
|
#include "packager/base/compiler_specific.h"
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
#include "base/time/time.h"
|
#include "packager/base/time/time.h"
|
||||||
#include "media/base/audio_decoder_config.h"
|
#include "packager/media/base/audio_decoder_config.h"
|
||||||
#include "media/base/media_log.h"
|
#include "packager/media/base/text_track_config.h"
|
||||||
#include "media/base/text_track_config.h"
|
#include "packager/media/base/video_decoder_config.h"
|
||||||
#include "media/base/video_decoder_config.h"
|
#include "packager/media/formats/webm/webm_audio_client.h"
|
||||||
#include "media/formats/webm/webm_audio_client.h"
|
#include "packager/media/formats/webm/webm_content_encodings_client.h"
|
||||||
#include "media/formats/webm/webm_content_encodings_client.h"
|
#include "packager/media/formats/webm/webm_parser.h"
|
||||||
#include "media/formats/webm/webm_parser.h"
|
#include "packager/media/formats/webm/webm_video_client.h"
|
||||||
#include "media/formats/webm/webm_video_client.h"
|
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
// Parser for WebM Tracks element.
|
// Parser for WebM Tracks element.
|
||||||
class MEDIA_EXPORT WebMTracksParser : public WebMParserClient {
|
class WebMTracksParser : public WebMParserClient {
|
||||||
public:
|
public:
|
||||||
WebMTracksParser(const scoped_refptr<MediaLog>& media_log,
|
explicit WebMTracksParser(bool ignore_text_tracks);
|
||||||
bool ignore_text_tracks);
|
|
||||||
~WebMTracksParser() override;
|
~WebMTracksParser() override;
|
||||||
|
|
||||||
// Parses a WebM Tracks element in |buf|.
|
// Parses a WebM Tracks element in |buf|.
|
||||||
|
@ -36,10 +35,10 @@ class MEDIA_EXPORT WebMTracksParser : public WebMParserClient {
|
||||||
// Returns -1 if the parse fails.
|
// Returns -1 if the parse fails.
|
||||||
// Returns 0 if more data is needed.
|
// Returns 0 if more data is needed.
|
||||||
// Returns the number of bytes parsed on success.
|
// Returns the number of bytes parsed on success.
|
||||||
int Parse(const uint8* buf, int size);
|
int Parse(const uint8_t* buf, int size);
|
||||||
|
|
||||||
int64 audio_track_num() const { return audio_track_num_; }
|
int64_t audio_track_num() const { return audio_track_num_; }
|
||||||
int64 video_track_num() const { return video_track_num_; }
|
int64_t video_track_num() const { return video_track_num_; }
|
||||||
|
|
||||||
// If TrackEntry DefaultDuration field existed for the associated audio or
|
// If TrackEntry DefaultDuration field existed for the associated audio or
|
||||||
// video track, returns that value converted from ns to base::TimeDelta with
|
// video track, returns that value converted from ns to base::TimeDelta with
|
||||||
|
@ -50,7 +49,7 @@ class MEDIA_EXPORT WebMTracksParser : public WebMParserClient {
|
||||||
base::TimeDelta GetVideoDefaultDuration(
|
base::TimeDelta GetVideoDefaultDuration(
|
||||||
const double timecode_scale_in_us) const;
|
const double timecode_scale_in_us) const;
|
||||||
|
|
||||||
const std::set<int64>& ignored_tracks() const { return ignored_tracks_; }
|
const std::set<int64_t>& ignored_tracks() const { return ignored_tracks_; }
|
||||||
|
|
||||||
const std::string& audio_encryption_key_id() const {
|
const std::string& audio_encryption_key_id() const {
|
||||||
return audio_encryption_key_id_;
|
return audio_encryption_key_id_;
|
||||||
|
@ -78,32 +77,31 @@ class MEDIA_EXPORT WebMTracksParser : public WebMParserClient {
|
||||||
// WebMParserClient implementation.
|
// WebMParserClient implementation.
|
||||||
WebMParserClient* OnListStart(int id) override;
|
WebMParserClient* OnListStart(int id) override;
|
||||||
bool OnListEnd(int id) override;
|
bool OnListEnd(int id) override;
|
||||||
bool OnUInt(int id, int64 val) override;
|
bool OnUInt(int id, int64_t val) override;
|
||||||
bool OnFloat(int id, double val) override;
|
bool OnFloat(int id, double val) override;
|
||||||
bool OnBinary(int id, const uint8* data, int size) override;
|
bool OnBinary(int id, const uint8_t* data, int size) override;
|
||||||
bool OnString(int id, const std::string& str) override;
|
bool OnString(int id, const std::string& str) override;
|
||||||
|
|
||||||
int64 track_type_;
|
int64_t track_type_;
|
||||||
int64 track_num_;
|
int64_t track_num_;
|
||||||
std::string track_name_;
|
std::string track_name_;
|
||||||
std::string track_language_;
|
std::string track_language_;
|
||||||
std::string codec_id_;
|
std::string codec_id_;
|
||||||
std::vector<uint8> codec_private_;
|
std::vector<uint8_t> codec_private_;
|
||||||
int64 seek_preroll_;
|
int64_t seek_preroll_;
|
||||||
int64 codec_delay_;
|
int64_t codec_delay_;
|
||||||
int64 default_duration_;
|
int64_t default_duration_;
|
||||||
scoped_ptr<WebMContentEncodingsClient> track_content_encodings_client_;
|
scoped_ptr<WebMContentEncodingsClient> track_content_encodings_client_;
|
||||||
|
|
||||||
int64 audio_track_num_;
|
int64_t audio_track_num_;
|
||||||
int64 audio_default_duration_;
|
int64_t audio_default_duration_;
|
||||||
int64 video_track_num_;
|
int64_t video_track_num_;
|
||||||
int64 video_default_duration_;
|
int64_t video_default_duration_;
|
||||||
bool ignore_text_tracks_;
|
bool ignore_text_tracks_;
|
||||||
TextTracks text_tracks_;
|
TextTracks text_tracks_;
|
||||||
std::set<int64> ignored_tracks_;
|
std::set<int64_t> ignored_tracks_;
|
||||||
std::string audio_encryption_key_id_;
|
std::string audio_encryption_key_id_;
|
||||||
std::string video_encryption_key_id_;
|
std::string video_encryption_key_id_;
|
||||||
scoped_refptr<MediaLog> media_log_;
|
|
||||||
|
|
||||||
WebMAudioClient audio_client_;
|
WebMAudioClient audio_client_;
|
||||||
AudioDecoderConfig audio_decoder_config_;
|
AudioDecoderConfig audio_decoder_config_;
|
||||||
|
@ -115,5 +113,6 @@ class MEDIA_EXPORT WebMTracksParser : public WebMParserClient {
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_WEBM_TRACKS_PARSER_H_
|
#endif // MEDIA_FORMATS_WEBM_WEBM_TRACKS_PARSER_H_
|
||||||
|
|
|
@ -2,15 +2,16 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "packager/media/formats/webm/webm_tracks_parser.h"
|
||||||
#include "media/base/channel_layout.h"
|
|
||||||
#include "media/base/mock_media_log.h"
|
#include <gmock/gmock.h>
|
||||||
#include "media/base/timestamp_constants.h"
|
#include <gtest/gtest.h>
|
||||||
#include "media/formats/webm/tracks_builder.h"
|
|
||||||
#include "media/formats/webm/webm_constants.h"
|
#include "packager/base/logging.h"
|
||||||
#include "media/formats/webm/webm_tracks_parser.h"
|
#include "packager/media/base/channel_layout.h"
|
||||||
#include "testing/gmock/include/gmock/gmock.h"
|
#include "packager/media/base/timestamp_constants.h"
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
#include "packager/media/formats/webm/tracks_builder.h"
|
||||||
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
using ::testing::HasSubstr;
|
using ::testing::HasSubstr;
|
||||||
using ::testing::InSequence;
|
using ::testing::InSequence;
|
||||||
|
@ -18,22 +19,22 @@ using ::testing::Return;
|
||||||
using ::testing::StrictMock;
|
using ::testing::StrictMock;
|
||||||
using ::testing::_;
|
using ::testing::_;
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
static const double kDefaultTimecodeScaleInUs = 1000.0; // 1 ms resolution
|
static const double kDefaultTimecodeScaleInUs = 1000.0; // 1 ms resolution
|
||||||
|
|
||||||
class WebMTracksParserTest : public testing::Test {
|
class WebMTracksParserTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
WebMTracksParserTest() : media_log_(new StrictMock<MockMediaLog>()) {}
|
WebMTracksParserTest() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void VerifyTextTrackInfo(const uint8* buffer,
|
void VerifyTextTrackInfo(const uint8_t* buffer,
|
||||||
int buffer_size,
|
int buffer_size,
|
||||||
TextKind text_kind,
|
TextKind text_kind,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& language) {
|
const std::string& language) {
|
||||||
scoped_ptr<WebMTracksParser> parser(
|
scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(false));
|
||||||
new WebMTracksParser(media_log_, false));
|
|
||||||
|
|
||||||
int result = parser->Parse(buffer, buffer_size);
|
int result = parser->Parse(buffer, buffer_size);
|
||||||
EXPECT_GT(result, 0);
|
EXPECT_GT(result, 0);
|
||||||
|
@ -51,8 +52,6 @@ class WebMTracksParserTest : public testing::Test {
|
||||||
EXPECT_TRUE(config.label() == name);
|
EXPECT_TRUE(config.label() == name);
|
||||||
EXPECT_TRUE(config.language() == language);
|
EXPECT_TRUE(config.language() == language);
|
||||||
}
|
}
|
||||||
|
|
||||||
scoped_refptr<StrictMock<MockMediaLog>> media_log_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(WebMTracksParserTest, SubtitleNoNameNoLang) {
|
TEST_F(WebMTracksParserTest, SubtitleNoNameNoLang) {
|
||||||
|
@ -61,7 +60,7 @@ TEST_F(WebMTracksParserTest, SubtitleNoNameNoLang) {
|
||||||
TracksBuilder tb;
|
TracksBuilder tb;
|
||||||
tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "", "");
|
tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "", "");
|
||||||
|
|
||||||
const std::vector<uint8> buf = tb.Finish();
|
const std::vector<uint8_t> buf = tb.Finish();
|
||||||
VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "", "");
|
VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +70,7 @@ TEST_F(WebMTracksParserTest, SubtitleYesNameNoLang) {
|
||||||
TracksBuilder tb;
|
TracksBuilder tb;
|
||||||
tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "Spock", "");
|
tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "Spock", "");
|
||||||
|
|
||||||
const std::vector<uint8> buf = tb.Finish();
|
const std::vector<uint8_t> buf = tb.Finish();
|
||||||
VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "Spock", "");
|
VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "Spock", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +80,7 @@ TEST_F(WebMTracksParserTest, SubtitleNoNameYesLang) {
|
||||||
TracksBuilder tb;
|
TracksBuilder tb;
|
||||||
tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "", "eng");
|
tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "", "eng");
|
||||||
|
|
||||||
const std::vector<uint8> buf = tb.Finish();
|
const std::vector<uint8_t> buf = tb.Finish();
|
||||||
VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "", "eng");
|
VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "", "eng");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +90,7 @@ TEST_F(WebMTracksParserTest, SubtitleYesNameYesLang) {
|
||||||
TracksBuilder tb;
|
TracksBuilder tb;
|
||||||
tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "Picard", "fre");
|
tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "Picard", "fre");
|
||||||
|
|
||||||
const std::vector<uint8> buf = tb.Finish();
|
const std::vector<uint8_t> buf = tb.Finish();
|
||||||
VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "Picard", "fre");
|
VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "Picard", "fre");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,11 +101,8 @@ TEST_F(WebMTracksParserTest, IgnoringTextTracks) {
|
||||||
tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "Subtitles", "fre");
|
tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "Subtitles", "fre");
|
||||||
tb.AddTextTrack(2, 2, kWebMCodecSubtitles, "Commentary", "fre");
|
tb.AddTextTrack(2, 2, kWebMCodecSubtitles, "Commentary", "fre");
|
||||||
|
|
||||||
const std::vector<uint8> buf = tb.Finish();
|
const std::vector<uint8_t> buf = tb.Finish();
|
||||||
scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(media_log_, true));
|
scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(true));
|
||||||
|
|
||||||
EXPECT_MEDIA_LOG(HasSubstr("Ignoring text track 1"));
|
|
||||||
EXPECT_MEDIA_LOG(HasSubstr("Ignoring text track 2"));
|
|
||||||
|
|
||||||
int result = parser->Parse(&buf[0], buf.size());
|
int result = parser->Parse(&buf[0], buf.size());
|
||||||
EXPECT_GT(result, 0);
|
EXPECT_GT(result, 0);
|
||||||
|
@ -114,12 +110,12 @@ TEST_F(WebMTracksParserTest, IgnoringTextTracks) {
|
||||||
|
|
||||||
EXPECT_EQ(parser->text_tracks().size(), 0u);
|
EXPECT_EQ(parser->text_tracks().size(), 0u);
|
||||||
|
|
||||||
const std::set<int64>& ignored_tracks = parser->ignored_tracks();
|
const std::set<int64_t>& ignored_tracks = parser->ignored_tracks();
|
||||||
EXPECT_TRUE(ignored_tracks.find(1) != ignored_tracks.end());
|
EXPECT_TRUE(ignored_tracks.find(1) != ignored_tracks.end());
|
||||||
EXPECT_TRUE(ignored_tracks.find(2) != ignored_tracks.end());
|
EXPECT_TRUE(ignored_tracks.find(2) != ignored_tracks.end());
|
||||||
|
|
||||||
// Test again w/o ignoring the test tracks.
|
// Test again w/o ignoring the test tracks.
|
||||||
parser.reset(new WebMTracksParser(media_log_, false));
|
parser.reset(new WebMTracksParser(false));
|
||||||
|
|
||||||
result = parser->Parse(&buf[0], buf.size());
|
result = parser->Parse(&buf[0], buf.size());
|
||||||
EXPECT_GT(result, 0);
|
EXPECT_GT(result, 0);
|
||||||
|
@ -137,9 +133,9 @@ TEST_F(WebMTracksParserTest, AudioVideoDefaultDurationUnset) {
|
||||||
TracksBuilder tb;
|
TracksBuilder tb;
|
||||||
tb.AddAudioTrack(1, 1, "A_VORBIS", "audio", "", -1, 2, 8000);
|
tb.AddAudioTrack(1, 1, "A_VORBIS", "audio", "", -1, 2, 8000);
|
||||||
tb.AddVideoTrack(2, 2, "V_VP8", "video", "", -1, 320, 240);
|
tb.AddVideoTrack(2, 2, "V_VP8", "video", "", -1, 320, 240);
|
||||||
const std::vector<uint8> buf = tb.Finish();
|
const std::vector<uint8_t> buf = tb.Finish();
|
||||||
|
|
||||||
scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(media_log_, true));
|
scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(true));
|
||||||
int result = parser->Parse(&buf[0], buf.size());
|
int result = parser->Parse(&buf[0], buf.size());
|
||||||
EXPECT_LE(0, result);
|
EXPECT_LE(0, result);
|
||||||
EXPECT_EQ(static_cast<int>(buf.size()), result);
|
EXPECT_EQ(static_cast<int>(buf.size()), result);
|
||||||
|
@ -166,9 +162,9 @@ TEST_F(WebMTracksParserTest, AudioVideoDefaultDurationSet) {
|
||||||
TracksBuilder tb;
|
TracksBuilder tb;
|
||||||
tb.AddAudioTrack(1, 1, "A_VORBIS", "audio", "", 12345678, 2, 8000);
|
tb.AddAudioTrack(1, 1, "A_VORBIS", "audio", "", 12345678, 2, 8000);
|
||||||
tb.AddVideoTrack(2, 2, "V_VP8", "video", "", 987654321, 320, 240);
|
tb.AddVideoTrack(2, 2, "V_VP8", "video", "", 987654321, 320, 240);
|
||||||
const std::vector<uint8> buf = tb.Finish();
|
const std::vector<uint8_t> buf = tb.Finish();
|
||||||
|
|
||||||
scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(media_log_, true));
|
scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(true));
|
||||||
int result = parser->Parse(&buf[0], buf.size());
|
int result = parser->Parse(&buf[0], buf.size());
|
||||||
EXPECT_LE(0, result);
|
EXPECT_LE(0, result);
|
||||||
EXPECT_EQ(static_cast<int>(buf.size()), result);
|
EXPECT_EQ(static_cast<int>(buf.size()), result);
|
||||||
|
@ -188,11 +184,9 @@ TEST_F(WebMTracksParserTest, InvalidZeroDefaultDurationSet) {
|
||||||
// Confirm parse error if TrackEntry DefaultDuration is present, but is 0ns.
|
// Confirm parse error if TrackEntry DefaultDuration is present, but is 0ns.
|
||||||
TracksBuilder tb(true);
|
TracksBuilder tb(true);
|
||||||
tb.AddAudioTrack(1, 1, "A_VORBIS", "audio", "", 0, 2, 8000);
|
tb.AddAudioTrack(1, 1, "A_VORBIS", "audio", "", 0, 2, 8000);
|
||||||
const std::vector<uint8> buf = tb.Finish();
|
const std::vector<uint8_t> buf = tb.Finish();
|
||||||
|
|
||||||
scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(media_log_, true));
|
scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(true));
|
||||||
|
|
||||||
EXPECT_MEDIA_LOG(HasSubstr("Illegal 0ns audio TrackEntry DefaultDuration"));
|
|
||||||
|
|
||||||
EXPECT_EQ(-1, parser->Parse(&buf[0], buf.size()));
|
EXPECT_EQ(-1, parser->Parse(&buf[0], buf.size()));
|
||||||
}
|
}
|
||||||
|
@ -202,10 +196,11 @@ TEST_F(WebMTracksParserTest, HighTrackUID) {
|
||||||
// (http://crbug.com/397067).
|
// (http://crbug.com/397067).
|
||||||
TracksBuilder tb(true);
|
TracksBuilder tb(true);
|
||||||
tb.AddAudioTrack(1, 1ULL << 31, "A_VORBIS", "audio", "", 40, 2, 8000);
|
tb.AddAudioTrack(1, 1ULL << 31, "A_VORBIS", "audio", "", 40, 2, 8000);
|
||||||
const std::vector<uint8> buf = tb.Finish();
|
const std::vector<uint8_t> buf = tb.Finish();
|
||||||
|
|
||||||
scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(media_log_, true));
|
scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(true));
|
||||||
EXPECT_GT(parser->Parse(&buf[0], buf.size()),0);
|
EXPECT_GT(parser->Parse(&buf[0], buf.size()),0);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/webm_video_client.h"
|
#include "packager/media/formats/webm/webm_video_client.h"
|
||||||
|
|
||||||
#include "media/base/video_decoder_config.h"
|
#include "packager/media/base/video_decoder_config.h"
|
||||||
#include "media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
WebMVideoClient::WebMVideoClient(const scoped_refptr<MediaLog>& media_log)
|
WebMVideoClient::WebMVideoClient() {
|
||||||
: media_log_(media_log) {
|
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,8 +31,10 @@ void WebMVideoClient::Reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMVideoClient::InitializeConfig(
|
bool WebMVideoClient::InitializeConfig(
|
||||||
const std::string& codec_id, const std::vector<uint8>& codec_private,
|
const std::string& codec_id,
|
||||||
bool is_encrypted, VideoDecoderConfig* config) {
|
const std::vector<uint8_t>& codec_private,
|
||||||
|
bool is_encrypted,
|
||||||
|
VideoDecoderConfig* config) {
|
||||||
DCHECK(config);
|
DCHECK(config);
|
||||||
|
|
||||||
VideoCodec video_codec = kUnknownVideoCodec;
|
VideoCodec video_codec = kUnknownVideoCodec;
|
||||||
|
@ -44,7 +46,7 @@ bool WebMVideoClient::InitializeConfig(
|
||||||
video_codec = kCodecVP9;
|
video_codec = kCodecVP9;
|
||||||
profile = VP9PROFILE_ANY;
|
profile = VP9PROFILE_ANY;
|
||||||
} else {
|
} else {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unsupported video codec_id " << codec_id;
|
LOG(ERROR) << "Unsupported video codec_id " << codec_id;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,12 +85,11 @@ bool WebMVideoClient::InitializeConfig(
|
||||||
if (display_width_ <= 0 || display_height_ <= 0)
|
if (display_width_ <= 0 || display_height_ <= 0)
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Unsupported display unit type "
|
LOG(ERROR) << "Unsupported display unit type " << display_unit_;
|
||||||
<< display_unit_;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
gfx::Size natural_size = gfx::Size(display_width_, display_height_);
|
gfx::Size natural_size = gfx::Size(display_width_, display_height_);
|
||||||
const uint8* extra_data = NULL;
|
const uint8_t* extra_data = NULL;
|
||||||
size_t extra_data_size = 0;
|
size_t extra_data_size = 0;
|
||||||
if (codec_private.size() > 0) {
|
if (codec_private.size() > 0) {
|
||||||
extra_data = &codec_private[0];
|
extra_data = &codec_private[0];
|
||||||
|
@ -101,8 +102,8 @@ bool WebMVideoClient::InitializeConfig(
|
||||||
return config->IsValidConfig();
|
return config->IsValidConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMVideoClient::OnUInt(int id, int64 val) {
|
bool WebMVideoClient::OnUInt(int id, int64_t val) {
|
||||||
int64* dst = NULL;
|
int64_t* dst = NULL;
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case kWebMIdPixelWidth:
|
case kWebMIdPixelWidth:
|
||||||
|
@ -140,9 +141,8 @@ bool WebMVideoClient::OnUInt(int id, int64 val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*dst != -1) {
|
if (*dst != -1) {
|
||||||
MEDIA_LOG(ERROR, media_log_) << "Multiple values for id " << std::hex << id
|
LOG(ERROR) << "Multiple values for id " << std::hex << id << " specified ("
|
||||||
<< " specified (" << *dst << " and " << val
|
<< *dst << " and " << val << ")";
|
||||||
<< ")";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ bool WebMVideoClient::OnUInt(int id, int64 val) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMVideoClient::OnBinary(int id, const uint8* data, int size) {
|
bool WebMVideoClient::OnBinary(int id, const uint8_t* data, int size) {
|
||||||
// Accept binary fields we don't care about for now.
|
// Accept binary fields we don't care about for now.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -161,3 +161,4 @@ bool WebMVideoClient::OnFloat(int id, double val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -8,16 +8,16 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "media/base/media_log.h"
|
#include "packager/media/formats/webm/webm_parser.h"
|
||||||
#include "media/formats/webm/webm_parser.h"
|
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
class VideoDecoderConfig;
|
class VideoDecoderConfig;
|
||||||
|
|
||||||
// Helper class used to parse a Video element inside a TrackEntry element.
|
// Helper class used to parse a Video element inside a TrackEntry element.
|
||||||
class WebMVideoClient : public WebMParserClient {
|
class WebMVideoClient : public WebMParserClient {
|
||||||
public:
|
public:
|
||||||
explicit WebMVideoClient(const scoped_refptr<MediaLog>& media_log);
|
WebMVideoClient();
|
||||||
~WebMVideoClient() override;
|
~WebMVideoClient() override;
|
||||||
|
|
||||||
// Reset this object's state so it can process a new video track element.
|
// Reset this object's state so it can process a new video track element.
|
||||||
|
@ -31,31 +31,31 @@ class WebMVideoClient : public WebMParserClient {
|
||||||
// video track element fields. The contents of |config| are undefined in this
|
// video track element fields. The contents of |config| are undefined in this
|
||||||
// case and should not be relied upon.
|
// case and should not be relied upon.
|
||||||
bool InitializeConfig(const std::string& codec_id,
|
bool InitializeConfig(const std::string& codec_id,
|
||||||
const std::vector<uint8>& codec_private,
|
const std::vector<uint8_t>& codec_private,
|
||||||
bool is_encrypted,
|
bool is_encrypted,
|
||||||
VideoDecoderConfig* config);
|
VideoDecoderConfig* config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// WebMParserClient implementation.
|
// WebMParserClient implementation.
|
||||||
bool OnUInt(int id, int64 val) override;
|
bool OnUInt(int id, int64_t val) override;
|
||||||
bool OnBinary(int id, const uint8* data, int size) override;
|
bool OnBinary(int id, const uint8_t* data, int size) override;
|
||||||
bool OnFloat(int id, double val) override;
|
bool OnFloat(int id, double val) override;
|
||||||
|
|
||||||
scoped_refptr<MediaLog> media_log_;
|
int64_t pixel_width_;
|
||||||
int64 pixel_width_;
|
int64_t pixel_height_;
|
||||||
int64 pixel_height_;
|
int64_t crop_bottom_;
|
||||||
int64 crop_bottom_;
|
int64_t crop_top_;
|
||||||
int64 crop_top_;
|
int64_t crop_left_;
|
||||||
int64 crop_left_;
|
int64_t crop_right_;
|
||||||
int64 crop_right_;
|
int64_t display_width_;
|
||||||
int64 display_width_;
|
int64_t display_height_;
|
||||||
int64 display_height_;
|
int64_t display_unit_;
|
||||||
int64 display_unit_;
|
int64_t alpha_mode_;
|
||||||
int64 alpha_mode_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(WebMVideoClient);
|
DISALLOW_COPY_AND_ASSIGN(WebMVideoClient);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_WEBM_VIDEO_CLIENT_H_
|
#endif // MEDIA_FORMATS_WEBM_WEBM_VIDEO_CLIENT_H_
|
||||||
|
|
|
@ -2,11 +2,13 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/webm_webvtt_parser.h"
|
#include "packager/media/formats/webm/webm_webvtt_parser.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
void WebMWebVTTParser::Parse(const uint8* payload, int payload_size,
|
void WebMWebVTTParser::Parse(const uint8_t* payload,
|
||||||
|
int payload_size,
|
||||||
std::string* id,
|
std::string* id,
|
||||||
std::string* settings,
|
std::string* settings,
|
||||||
std::string* content) {
|
std::string* content) {
|
||||||
|
@ -14,10 +16,8 @@ void WebMWebVTTParser::Parse(const uint8* payload, int payload_size,
|
||||||
parser.Parse(id, settings, content);
|
parser.Parse(id, settings, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
WebMWebVTTParser::WebMWebVTTParser(const uint8* payload, int payload_size)
|
WebMWebVTTParser::WebMWebVTTParser(const uint8_t* payload, int payload_size)
|
||||||
: ptr_(payload),
|
: ptr_(payload), ptr_end_(payload + payload_size) {}
|
||||||
ptr_end_(payload + payload_size) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebMWebVTTParser::Parse(std::string* id,
|
void WebMWebVTTParser::Parse(std::string* id,
|
||||||
std::string* settings,
|
std::string* settings,
|
||||||
|
@ -27,7 +27,7 @@ void WebMWebVTTParser::Parse(std::string* id,
|
||||||
content->assign(ptr_, ptr_end_);
|
content->assign(ptr_, ptr_end_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMWebVTTParser::GetByte(uint8* byte) {
|
bool WebMWebVTTParser::GetByte(uint8_t* byte) {
|
||||||
if (ptr_ >= ptr_end_)
|
if (ptr_ >= ptr_end_)
|
||||||
return false; // indicates end-of-stream
|
return false; // indicates end-of-stream
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ void WebMWebVTTParser::ParseLine(std::string* line) {
|
||||||
};
|
};
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint8 byte;
|
uint8_t byte;
|
||||||
|
|
||||||
if (!GetByte(&byte) || byte == kLF)
|
if (!GetByte(&byte) || byte == kLF)
|
||||||
return;
|
return;
|
||||||
|
@ -76,3 +76,4 @@ void WebMWebVTTParser::ParseLine(std::string* line) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
|
@ -5,17 +5,20 @@
|
||||||
#ifndef MEDIA_FORMATS_WEBM_WEBM_WEBVTT_PARSER_H_
|
#ifndef MEDIA_FORMATS_WEBM_WEBM_WEBVTT_PARSER_H_
|
||||||
#define MEDIA_FORMATS_WEBM_WEBM_WEBVTT_PARSER_H_
|
#define MEDIA_FORMATS_WEBM_WEBM_WEBVTT_PARSER_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "packager/base/macros.h"
|
||||||
#include "media/base/media_export.h"
|
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
class MEDIA_EXPORT WebMWebVTTParser {
|
class WebMWebVTTParser {
|
||||||
public:
|
public:
|
||||||
// Utility function to parse the WebVTT cue from a byte stream.
|
// Utility function to parse the WebVTT cue from a byte stream.
|
||||||
static void Parse(const uint8* payload, int payload_size,
|
static void Parse(const uint8_t* payload,
|
||||||
|
int payload_size,
|
||||||
std::string* id,
|
std::string* id,
|
||||||
std::string* settings,
|
std::string* settings,
|
||||||
std::string* content);
|
std::string* content);
|
||||||
|
@ -23,13 +26,13 @@ class MEDIA_EXPORT WebMWebVTTParser {
|
||||||
private:
|
private:
|
||||||
// The payload is the embedded WebVTT cue, stored in a WebM block.
|
// The payload is the embedded WebVTT cue, stored in a WebM block.
|
||||||
// The parser treats this as a UTF-8 byte stream.
|
// The parser treats this as a UTF-8 byte stream.
|
||||||
WebMWebVTTParser(const uint8* payload, int payload_size);
|
WebMWebVTTParser(const uint8_t* payload, int payload_size);
|
||||||
|
|
||||||
// Parse the cue identifier, settings, and content from the stream.
|
// Parse the cue identifier, settings, and content from the stream.
|
||||||
void Parse(std::string* id, std::string* settings, std::string* content);
|
void Parse(std::string* id, std::string* settings, std::string* content);
|
||||||
// Remove a byte from the stream, advancing the stream pointer.
|
// Remove a byte from the stream, advancing the stream pointer.
|
||||||
// Returns true if a character was returned; false means "end of stream".
|
// Returns true if a character was returned; false means "end of stream".
|
||||||
bool GetByte(uint8* byte);
|
bool GetByte(uint8_t* byte);
|
||||||
|
|
||||||
// Backup the stream pointer.
|
// Backup the stream pointer.
|
||||||
void UngetByte();
|
void UngetByte();
|
||||||
|
@ -38,12 +41,13 @@ class MEDIA_EXPORT WebMWebVTTParser {
|
||||||
void ParseLine(std::string* line);
|
void ParseLine(std::string* line);
|
||||||
|
|
||||||
// Represents the portion of the stream that has not been consumed yet.
|
// Represents the portion of the stream that has not been consumed yet.
|
||||||
const uint8* ptr_;
|
const uint8_t* ptr_;
|
||||||
const uint8* const ptr_end_;
|
const uint8_t* const ptr_end_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(WebMWebVTTParser);
|
DISALLOW_COPY_AND_ASSIGN(WebMWebVTTParser);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
#endif // MEDIA_FORMATS_WEBM_WEBM_WEBVTT_PARSER_H_
|
#endif // MEDIA_FORMATS_WEBM_WEBM_WEBVTT_PARSER_H_
|
||||||
|
|
|
@ -2,21 +2,23 @@
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "media/formats/webm/webm_webvtt_parser.h"
|
#include "packager/media/formats/webm/webm_webvtt_parser.h"
|
||||||
#include "testing/gmock/include/gmock/gmock.h"
|
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
#include <gmock/gmock.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
using ::testing::InSequence;
|
using ::testing::InSequence;
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
typedef std::vector<uint8> Cue;
|
typedef std::vector<uint8_t> Cue;
|
||||||
|
|
||||||
static Cue EncodeCue(const std::string& id,
|
static Cue EncodeCue(const std::string& id,
|
||||||
const std::string& settings,
|
const std::string& settings,
|
||||||
const std::string& content) {
|
const std::string& content) {
|
||||||
const std::string result = id + '\n' + settings + '\n' + content;
|
const std::string result = id + '\n' + settings + '\n' + content;
|
||||||
const uint8* const buf = reinterpret_cast<const uint8*>(result.data());
|
const uint8_t* const buf = reinterpret_cast<const uint8_t*>(result.data());
|
||||||
return Cue(buf, buf + result.length());
|
return Cue(buf, buf + result.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,3 +105,4 @@ TEST_F(WebMWebVTTParserTest, Content) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
Loading…
Reference in New Issue