Fix WebM keyframe detection in BlockGroup

The right way to detect the presence of a keyframe in a BlockGroup
is to look for the absence of the ReferenceBlock element [1].

Closes b/30433206

[1] https://matroska.org/technical/specs/index.html#ReferenceBlock

Change-Id: I2b3c8704cbabcd5cbee38448e5528425865561a4
This commit is contained in:
Kongqun Yang 2016-07-29 16:06:20 -07:00 committed by KongQun Yang
parent db92c9a22b
commit d501b457d0
8 changed files with 172 additions and 154 deletions

View File

@ -143,6 +143,14 @@ class PackagerAppTest(unittest.TestCase):
self._DiffGold(self.output[1], 'bear-320x240-vp9-golden.webm')
self._DiffGold(self.mpd_output, 'bear-320x240-vp9-opus-webm-golden.mpd')
def testPackageVp9WebmWithBlockgroup(self):
self.packager.Package(
self._GetStreams(['video'],
output_format='webm',
test_files=['bear-vp9-blockgroup.webm']),
self._GetFlags())
self._DiffGold(self.output[0], 'bear-vp9-blockgroup-golden.webm')
def testPackageVorbisWebm(self):
self.packager.Package(
self._GetStreams(['audio'],

Binary file not shown.

View File

@ -40,6 +40,11 @@ static const uint8_t kBlockGroupHeaderWithoutBlockDuration[] = {
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Block(size = 0)
};
static const uint8_t kBlockGroupReferenceBlock[] = {
0xFB, // ReferenceBlock ID
0x81, 0x00, // ReferenceBlock (size=1, value=0)
};
enum {
kClusterSizeOffset = 4,
kClusterTimecodeOffset = 14,
@ -99,17 +104,21 @@ void ClusterBuilder::AddBlockGroup(int track_num,
int64_t timecode,
int duration,
int flags,
bool is_key_frame,
const uint8_t* data,
int size) {
AddBlockGroupInternal(track_num, timecode, true, duration, flags, data, size);
AddBlockGroupInternal(track_num, timecode, true, duration, flags,
is_key_frame, data, size);
}
void ClusterBuilder::AddBlockGroupWithoutBlockDuration(int track_num,
int64_t timecode,
int flags,
bool is_key_frame,
const uint8_t* data,
int size) {
AddBlockGroupInternal(track_num, timecode, false, 0, flags, data, size);
AddBlockGroupInternal(track_num, timecode, false, 0, flags, is_key_frame,
data, size);
}
void ClusterBuilder::AddBlockGroupInternal(int track_num,
@ -117,6 +126,7 @@ void ClusterBuilder::AddBlockGroupInternal(int track_num,
bool include_block_duration,
int duration,
int flags,
bool is_key_frame,
const uint8_t* data,
int size) {
int block_size = size + 4;
@ -126,6 +136,9 @@ void ClusterBuilder::AddBlockGroupInternal(int track_num,
} else {
bytes_needed += sizeof(kBlockGroupHeaderWithoutBlockDuration);
}
if (!is_key_frame) {
bytes_needed += sizeof(kBlockGroupReferenceBlock);
}
int block_group_size = bytes_needed - 9;
@ -155,7 +168,10 @@ void ClusterBuilder::AddBlockGroupInternal(int track_num,
flags &= 0x0f;
WriteBlock(buf, track_num, timecode, flags, data, size);
buf += size + 4;
if (!is_key_frame)
memcpy(buf, kBlockGroupReferenceBlock, sizeof(kBlockGroupReferenceBlock));
bytes_used_ += bytes_needed;
}

View File

@ -41,11 +41,13 @@ class ClusterBuilder {
int64_t timecode,
int duration,
int flags,
bool is_key_frame,
const uint8_t* data,
int size);
void AddBlockGroupWithoutBlockDuration(int track_num,
int64_t timecode,
int flags,
bool is_key_frame,
const uint8_t* data,
int size);
@ -58,6 +60,7 @@ class ClusterBuilder {
bool include_block_duration,
int duration,
int flags,
bool is_key_frame,
const uint8_t* data,
int size);
void Reset();

View File

@ -23,27 +23,6 @@ namespace {
const int64_t kMicrosecondsPerMillisecond = 1000;
// Helper function used to inspect block data to determine if the
// block is a keyframe.
// |data| contains the bytes in the block.
// |size| indicates the number of bytes in |data|.
bool IsKeyframe(bool is_video, Codec codec, const uint8_t* data, int size) {
// For now, assume that all blocks are keyframes for datatypes other than
// video. This is a valid assumption for Vorbis, WebVTT, & Opus.
if (!is_video)
return true;
switch (codec) {
case kCodecVP8:
return VP8Parser::IsKeyframe(data, size);
case kCodecVP9:
return VP9Parser::IsKeyframe(data, size);
default:
NOTIMPLEMENTED() << "Unsupported codec " << codec;
return false;
}
}
} // namespace
WebMClusterParser::WebMClusterParser(
@ -151,6 +130,7 @@ WebMParserClient* WebMClusterParser::OnListStart(int id) {
block_duration_ = -1;
discard_padding_ = -1;
discard_padding_set_ = false;
reference_block_set_ = false;
} else if (id == kWebMIdBlockAdditions) {
block_add_id_ = -1;
block_additional_data_.reset();
@ -170,10 +150,10 @@ bool WebMClusterParser::OnListEnd(int id) {
return false;
}
bool result = ParseBlock(false, block_data_.get(), block_data_size_,
block_additional_data_.get(),
bool result = ParseBlock(
false, block_data_.get(), block_data_size_, block_additional_data_.get(),
block_additional_data_size_, block_duration_,
discard_padding_set_ ? discard_padding_ : 0);
discard_padding_set_ ? discard_padding_ : 0, reference_block_set_);
block_data_.reset();
block_data_size_ = -1;
block_duration_ = -1;
@ -182,6 +162,7 @@ bool WebMClusterParser::OnListEnd(int id) {
block_additional_data_size_ = 0;
discard_padding_ = -1;
discard_padding_set_ = false;
reference_block_set_ = false;
return result;
}
@ -212,7 +193,8 @@ bool WebMClusterParser::ParseBlock(bool is_simple_block,
const uint8_t* additional,
int additional_size,
int duration,
int64_t discard_padding) {
int64_t discard_padding,
bool reference_block_set) {
if (size < 4)
return false;
@ -237,17 +219,24 @@ bool WebMClusterParser::ParseBlock(bool is_simple_block,
if (timecode & 0x8000)
timecode |= ~0xffff;
// The first bit of the flags is set when a SimpleBlock contains only
// keyframes. If this is a Block, then keyframe is inferred by the absence of
// the ReferenceBlock Element.
// http://www.matroska.org/technical/specs/index.html
bool is_key_frame =
is_simple_block ? (flags & 0x80) != 0 : !reference_block_set;
const uint8_t* frame_data = buf + 4;
int frame_size = size - (frame_data - buf);
return OnBlock(is_simple_block, track_num, timecode, duration, flags,
frame_data, frame_size, additional, additional_size,
discard_padding);
return OnBlock(is_simple_block, track_num, timecode, duration, frame_data,
frame_size, additional, additional_size, discard_padding,
is_key_frame);
}
bool WebMClusterParser::OnBinary(int id, const uint8_t* data, int size) {
switch (id) {
case kWebMIdSimpleBlock:
return ParseBlock(true, data, size, NULL, 0, -1, 0);
return ParseBlock(true, data, size, NULL, 0, -1, 0, false);
case kWebMIdBlock:
if (block_data_) {
@ -293,6 +282,12 @@ bool WebMClusterParser::OnBinary(int id, const uint8_t* data, int size) {
return true;
}
case kWebMIdReferenceBlock:
// We use ReferenceBlock to determine whether the current Block contains a
// keyframe or not. Other than that, we don't care about the value of the
// ReferenceBlock element itself.
reference_block_set_ = true;
return true;
default:
return true;
}
@ -302,12 +297,12 @@ bool WebMClusterParser::OnBlock(bool is_simple_block,
int track_num,
int timecode,
int block_duration,
int flags,
const uint8_t* data,
int size,
const uint8_t* additional,
int additional_size,
int64_t discard_padding) {
int64_t discard_padding,
bool is_key_frame) {
DCHECK_GE(size, 0);
if (cluster_timecode_ == -1) {
LOG(ERROR) << "Got a block before cluster timecode.";
@ -358,18 +353,6 @@ bool WebMClusterParser::OnBlock(bool is_simple_block,
scoped_refptr<MediaSample> buffer;
if (stream_type != kStreamText) {
// The first bit of the flags is set when a SimpleBlock contains only
// keyframes. If this is a Block, then inspection of the payload is
// necessary to determine whether it contains a keyframe or not.
// http://www.matroska.org/technical/specs/index.html
bool is_keyframe =
is_simple_block
? (flags & 0x80) != 0
: IsKeyframe(stream_type == kStreamVideo,
video_stream_info_ ? video_stream_info_->codec()
: kUnknownCodec,
data, size);
// Every encrypted Block has a signal byte and IV prepended to it. Current
// encrypted WebM request for comments specification is here
// http://wiki.webmproject.org/encryption/webm-encryption-rfc
@ -385,7 +368,7 @@ bool WebMClusterParser::OnBlock(bool is_simple_block,
}
buffer = MediaSample::CopyFrom(data + data_offset, size - data_offset,
additional, additional_size, is_keyframe);
additional, additional_size, is_key_frame);
if (decrypt_config) {
if (!decryptor_source_) {

View File

@ -163,17 +163,18 @@ class WebMClusterParser : public WebMParserClient {
const uint8_t* additional,
int additional_size,
int duration,
int64_t discard_padding);
int64_t discard_padding,
bool reference_block_set);
bool OnBlock(bool is_simple_block,
int track_num,
int timecode,
int duration,
int flags,
const uint8_t* data,
int size,
const uint8_t* additional,
int additional_size,
int64_t discard_padding);
int64_t discard_padding,
bool is_key_frame);
// Resets the Track objects associated with each text track.
void ResetTextTracks();
@ -215,6 +216,8 @@ class WebMClusterParser : public WebMParserClient {
int64_t discard_padding_ = -1;
bool discard_padding_set_ = false;
bool reference_block_set_ = false;
int64_t cluster_timecode_ = -1;
int64_t cluster_start_time_;
bool cluster_ended_ = false;

View File

@ -121,17 +121,19 @@ struct BlockInfo {
// Default data will be used if no data given.
const uint8_t* data;
int data_length;
bool is_key_frame;
};
const BlockInfo kDefaultBlockInfo[] = {
{kAudioTrackNum, 0, 23, true, NULL, 0},
{kAudioTrackNum, 23, 23, true, NULL, 0},
{kAudioTrackNum, 0, 23, true, NULL, 0, true},
{kAudioTrackNum, 23, 23, true, NULL, 0, true},
// Assumes not using DefaultDuration
{kVideoTrackNum, 33, 34, true, NULL, 0},
{kAudioTrackNum, 46, 23, true, NULL, 0},
{kVideoTrackNum, 67, 33, false, NULL, 0},
{kAudioTrackNum, 69, 23, false, NULL, 0},
{kVideoTrackNum, 100, 33, false, NULL, 0},
{kVideoTrackNum, 33, 34, true, NULL, 0, true},
{kAudioTrackNum, 46, 23, true, NULL, 0, false},
{kVideoTrackNum, 67, 33, false, NULL, 0, true},
{kAudioTrackNum, 69, 23, false, NULL, 0, false},
{kVideoTrackNum, 100, 33, false, NULL, 0, false},
};
const uint8_t kEncryptedFrame[] = {
@ -203,20 +205,22 @@ scoped_ptr<Cluster> CreateCluster(int timecode,
if (block_info[i].use_simple_block) {
CHECK_GE(block_info[i].duration, 0);
cb.AddSimpleBlock(block_info[i].track_num, block_info[i].timestamp, 0,
data, data_length);
continue;
}
if (block_info[i].duration < 0) {
cb.AddBlockGroupWithoutBlockDuration(block_info[i].track_num,
block_info[i].timestamp, 0, data,
cb.AddSimpleBlock(block_info[i].track_num, block_info[i].timestamp,
block_info[i].is_key_frame ? 0x80 : 0x00, data,
data_length);
continue;
}
if (block_info[i].duration < 0) {
cb.AddBlockGroupWithoutBlockDuration(
block_info[i].track_num, block_info[i].timestamp, 0,
block_info[i].is_key_frame, data, data_length);
continue;
}
cb.AddBlockGroup(block_info[i].track_num, block_info[i].timestamp,
block_info[i].duration, 0, data, data_length);
block_info[i].duration, 0, block_info[i].is_key_frame,
data, data_length);
}
return cb.Finish();
@ -277,6 +281,7 @@ bool VerifyBuffersHelper(const BufferQueue& audio_buffers,
buffer->pts());
EXPECT_EQ(std::abs(block_info[i].duration) * kMicrosecondsPerMillisecond,
buffer->duration());
EXPECT_EQ(block_info[i].is_key_frame, buffer->is_key_frame());
}
return true;
@ -476,29 +481,30 @@ TEST_F(WebMClusterParserTest, TracksWithSampleMissingDuration) {
const BlockInfo kBlockInfo[] = {
// Note that for simple blocks, duration is not encoded.
{kVideoTrackNum, 0, 0, true, NULL, 0},
{kAudioTrackNum, 0, 23, false, NULL, 0},
{kTextTrackNum, 10, 42, false, NULL, 0},
{kAudioTrackNum, 23, 0, true, NULL, 0},
{kVideoTrackNum, 33, 0, true, NULL, 0},
{kAudioTrackNum, 36, 0, true, NULL, 0},
{kVideoTrackNum, 66, 0, true, NULL, 0},
{kAudioTrackNum, 70, 0, true, NULL, 0},
{kAudioTrackNum, 83, 0, true, NULL, 0},
{kVideoTrackNum, 0, 0, true, NULL, 0, false},
{kAudioTrackNum, 0, 23, false, NULL, 0, false},
{kTextTrackNum, 10, 42, false, NULL, 0, true},
{kAudioTrackNum, 23, 0, true, NULL, 0, false},
{kVideoTrackNum, 33, 0, true, NULL, 0, false},
{kAudioTrackNum, 36, 0, true, NULL, 0, false},
{kVideoTrackNum, 66, 0, true, NULL, 0, false},
{kAudioTrackNum, 70, 0, true, NULL, 0, false},
{kAudioTrackNum, 83, 0, true, NULL, 0, false},
};
// Samples are not emitted in the same order as |kBlockInfo| due to missing of
// duration in some samples.
const BlockInfo kExpectedBlockInfo[] = {
{kAudioTrackNum, 0, 23, false, NULL, 0},
{kTextTrackNum, 10, 42, false, NULL, 0},
{kVideoTrackNum, 0, 33, true, NULL, 0},
{kAudioTrackNum, 23, 13, true, NULL, 0},
{kVideoTrackNum, 33, 33, true, NULL, 0},
{kAudioTrackNum, 36, 34, true, NULL, 0},
{kAudioTrackNum, 70, 13, true, NULL, 0},
{kAudioTrackNum, 83, kTestAudioFrameDefaultDurationInMs, true, NULL, 0},
{kVideoTrackNum, 66, kExpectedVideoEstimationInMs, true, NULL, 0},
{kAudioTrackNum, 0, 23, false, NULL, 0, false},
{kTextTrackNum, 10, 42, false, NULL, 0, true},
{kVideoTrackNum, 0, 33, true, NULL, 0, false},
{kAudioTrackNum, 23, 13, true, NULL, 0, false},
{kVideoTrackNum, 33, 33, true, NULL, 0, false},
{kAudioTrackNum, 36, 34, true, NULL, 0, false},
{kAudioTrackNum, 70, 13, true, NULL, 0, false},
{kAudioTrackNum, 83, kTestAudioFrameDefaultDurationInMs, true, NULL, 0,
false},
{kVideoTrackNum, 66, kExpectedVideoEstimationInMs, true, NULL, 0, false},
};
const int kExpectedBuffersOnPartialCluster[] = {
0, // Video simple block without duration should be held back
@ -609,8 +615,8 @@ TEST_F(WebMClusterParserTest, ParseClusterWithMultipleCalls) {
// one of these scenarios.
TEST_F(WebMClusterParserTest, ParseBlockGroup) {
const BlockInfo kBlockInfo[] = {
{kAudioTrackNum, 0, 23, false, NULL, 0},
{kVideoTrackNum, 33, 34, false, NULL, 0},
{kAudioTrackNum, 0, 23, false, NULL, 0, true},
{kVideoTrackNum, 33, 34, false, NULL, 0, true},
};
int block_count = arraysize(kBlockInfo);
@ -635,11 +641,11 @@ TEST_F(WebMClusterParserTest, ParseBlockGroup) {
TEST_F(WebMClusterParserTest, ParseSimpleBlockAndBlockGroupMixture) {
const BlockInfo kBlockInfo[] = {
{kAudioTrackNum, 0, 23, true, NULL, 0},
{kAudioTrackNum, 23, 23, false, NULL, 0},
{kVideoTrackNum, 33, 34, true, NULL, 0},
{kAudioTrackNum, 46, 23, false, NULL, 0},
{kVideoTrackNum, 67, 33, false, NULL, 0},
{kAudioTrackNum, 0, 23, true, NULL, 0, false},
{kAudioTrackNum, 23, 23, false, NULL, 0, false},
{kVideoTrackNum, 33, 34, true, NULL, 0, false},
{kAudioTrackNum, 46, 23, false, NULL, 0, false},
{kVideoTrackNum, 67, 33, false, NULL, 0, false},
};
int block_count = arraysize(kBlockInfo);
scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
@ -656,21 +662,21 @@ TEST_F(WebMClusterParserTest, IgnoredTracks) {
parser_.reset(CreateParserWithIgnoredTracks(ignored_tracks));
const BlockInfo kInputBlockInfo[] = {
{kAudioTrackNum, 0, 23, true, NULL, 0},
{kAudioTrackNum, 23, 23, true, NULL, 0},
{kVideoTrackNum, 33, 34, true, NULL, 0},
{kTextTrackNum, 33, 99, true, NULL, 0},
{kAudioTrackNum, 46, 23, true, NULL, 0},
{kVideoTrackNum, 67, 34, true, NULL, 0},
{kAudioTrackNum, 0, 23, true, NULL, 0, false},
{kAudioTrackNum, 23, 23, true, NULL, 0, false},
{kVideoTrackNum, 33, 34, true, NULL, 0, false},
{kTextTrackNum, 33, 99, true, NULL, 0, false},
{kAudioTrackNum, 46, 23, true, NULL, 0, false},
{kVideoTrackNum, 67, 34, true, NULL, 0, false},
};
int input_block_count = arraysize(kInputBlockInfo);
const BlockInfo kOutputBlockInfo[] = {
{kAudioTrackNum, 0, 23, true, NULL, 0},
{kAudioTrackNum, 23, 23, true, NULL, 0},
{kVideoTrackNum, 33, 34, true, NULL, 0},
{kAudioTrackNum, 46, 23, true, NULL, 0},
{kVideoTrackNum, 67, 34, true, NULL, 0},
{kAudioTrackNum, 0, 23, true, NULL, 0, false},
{kAudioTrackNum, 23, 23, true, NULL, 0, false},
{kVideoTrackNum, 33, 34, true, NULL, 0, false},
{kAudioTrackNum, 46, 23, true, NULL, 0, false},
{kVideoTrackNum, 67, 34, true, NULL, 0, false},
};
int output_block_count = arraysize(kOutputBlockInfo);
@ -694,13 +700,13 @@ TEST_F(WebMClusterParserTest, ParseTextTracks) {
kNoTimestamp, kNoTimestamp, text_tracks));
const BlockInfo kInputBlockInfo[] = {
{kAudioTrackNum, 0, 23, true, NULL, 0},
{kAudioTrackNum, 23, 23, true, NULL, 0},
{kVideoTrackNum, 33, 34, true, NULL, 0},
{kTextTrackNum, 33, 42, false, NULL, 0},
{kAudioTrackNum, 46, 23, true, NULL, 0},
{kTextTrackNum, 55, 44, false, NULL, 0},
{kVideoTrackNum, 67, 34, true, NULL, 0},
{kAudioTrackNum, 0, 23, true, NULL, 0, false},
{kAudioTrackNum, 23, 23, true, NULL, 0, false},
{kVideoTrackNum, 33, 34, true, NULL, 0, false},
{kTextTrackNum, 33, 42, false, NULL, 0, true},
{kAudioTrackNum, 46, 23, true, NULL, 0, false},
{kTextTrackNum, 55, 44, false, NULL, 0, true},
{kVideoTrackNum, 67, 34, true, NULL, 0, false},
};
int input_block_count = arraysize(kInputBlockInfo);
@ -724,7 +730,7 @@ TEST_F(WebMClusterParserTest, TextTracksSimpleBlock) {
kNoTimestamp, kNoTimestamp, text_tracks));
const BlockInfo kInputBlockInfo[] = {
{ kTextTrackNum, 33, 42, true },
{kTextTrackNum, 33, 42, true, NULL, 0, false},
};
int input_block_count = arraysize(kInputBlockInfo);
@ -753,14 +759,14 @@ TEST_F(WebMClusterParserTest, ParseMultipleTextTracks) {
kNoTimestamp, kNoTimestamp, text_tracks));
const BlockInfo kInputBlockInfo[] = {
{kAudioTrackNum, 0, 23, true, NULL, 0},
{kAudioTrackNum, 23, 23, true, NULL, 0},
{kVideoTrackNum, 33, 34, true, NULL, 0},
{kSubtitleTextTrackNum, 33, 42, false, NULL, 0},
{kAudioTrackNum, 46, 23, true, NULL, 0},
{kCaptionTextTrackNum, 55, 44, false, NULL, 0},
{kVideoTrackNum, 67, 34, true, NULL, 0},
{kSubtitleTextTrackNum, 67, 33, false, NULL, 0},
{kAudioTrackNum, 0, 23, true, NULL, 0, false},
{kAudioTrackNum, 23, 23, true, NULL, 0, false},
{kVideoTrackNum, 33, 34, true, NULL, 0, false},
{kSubtitleTextTrackNum, 33, 42, false, NULL, 0, false},
{kAudioTrackNum, 46, 23, true, NULL, 0, false},
{kCaptionTextTrackNum, 55, 44, false, NULL, 0, false},
{kVideoTrackNum, 67, 34, true, NULL, 0, false},
{kSubtitleTextTrackNum, 67, 33, false, NULL, 0, false},
};
int input_block_count = arraysize(kInputBlockInfo);
@ -907,7 +913,7 @@ TEST_F(WebMClusterParserTest, ParseInvalidTextBlockGroupWithoutDuration) {
kNoTimestamp, kNoTimestamp, text_tracks));
const BlockInfo kBlockInfo[] = {
{ kTextTrackNum, 33, -42, false },
{kTextTrackNum, 33, -42, false, NULL, 0, false},
};
int block_count = arraysize(kBlockInfo);
scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
@ -924,13 +930,15 @@ TEST_F(WebMClusterParserTest, ParseWithDefaultDurationsSimpleBlocks) {
const BlockInfo kBlockInfo[] = {
// Note that for simple blocks, duration is not encoded.
{kAudioTrackNum, 0, 23, true, NULL, 0},
{kAudioTrackNum, 23, 23, true, NULL, 0},
{kVideoTrackNum, 33, 34, true, NULL, 0},
{kAudioTrackNum, 46, 23, true, NULL, 0},
{kVideoTrackNum, 67, 33, true, NULL, 0},
{kAudioTrackNum, 69, kTestAudioFrameDefaultDurationInMs, true, NULL, 0},
{kVideoTrackNum, 100, kTestVideoFrameDefaultDurationInMs, true, NULL, 0},
{kAudioTrackNum, 0, 23, true, NULL, 0, false},
{kAudioTrackNum, 23, 23, true, NULL, 0, false},
{kVideoTrackNum, 33, 34, true, NULL, 0, false},
{kAudioTrackNum, 46, 23, true, NULL, 0, false},
{kVideoTrackNum, 67, 33, true, NULL, 0, false},
{kAudioTrackNum, 69, kTestAudioFrameDefaultDurationInMs, true, NULL, 0,
false},
{kVideoTrackNum, 100, kTestVideoFrameDefaultDurationInMs, true, NULL, 0,
false},
};
int block_count = arraysize(kBlockInfo);
@ -958,13 +966,13 @@ TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsSimpleBlocks) {
// Flush() is called. We use the maximum seen so far for estimation.
const BlockInfo kBlockInfo1[] = {
{kAudioTrackNum, 0, 23, true, NULL, 0},
{kAudioTrackNum, 23, 22, true, NULL, 0},
{kVideoTrackNum, 33, 33, true, NULL, 0},
{kAudioTrackNum, 45, 23, true, NULL, 0},
{kVideoTrackNum, 66, 34, true, NULL, 0},
{kAudioTrackNum, 68, 24, true, NULL, 0},
{kVideoTrackNum, 100, 35, true, NULL, 0},
{kAudioTrackNum, 0, 23, true, NULL, 0, false},
{kAudioTrackNum, 23, 22, true, NULL, 0, false},
{kVideoTrackNum, 33, 33, true, NULL, 0, false},
{kAudioTrackNum, 45, 23, true, NULL, 0, false},
{kVideoTrackNum, 66, 34, true, NULL, 0, false},
{kAudioTrackNum, 68, 24, true, NULL, 0, false},
{kVideoTrackNum, 100, 35, true, NULL, 0, false},
};
int block_count1 = arraysize(kBlockInfo1);
@ -984,8 +992,8 @@ TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsSimpleBlocks) {
const int kExpectedAudioEstimationInMs = 24;
const int kExpectedVideoEstimationInMs = 35;
const BlockInfo kBlockInfo2[] = {
{kAudioTrackNum, 92, kExpectedAudioEstimationInMs, true, NULL, 0},
{kVideoTrackNum, 135, kExpectedVideoEstimationInMs, true, NULL, 0},
{kAudioTrackNum, 92, kExpectedAudioEstimationInMs, true, NULL, 0, false},
{kVideoTrackNum, 135, kExpectedVideoEstimationInMs, true, NULL, 0, false},
};
int block_count2 = arraysize(kBlockInfo2);
@ -1010,13 +1018,13 @@ TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsBlockGroups) {
// for each track when Flush() is called. We use the maximum seen so far.
const BlockInfo kBlockInfo1[] = {
{kAudioTrackNum, 0, -23, false, NULL, 0},
{kAudioTrackNum, 23, -22, false, NULL, 0},
{kVideoTrackNum, 33, -33, false, NULL, 0},
{kAudioTrackNum, 45, -23, false, NULL, 0},
{kVideoTrackNum, 66, -34, false, NULL, 0},
{kAudioTrackNum, 68, -24, false, NULL, 0},
{kVideoTrackNum, 100, -35, false, NULL, 0},
{kAudioTrackNum, 0, -23, false, NULL, 0, false},
{kAudioTrackNum, 23, -22, false, NULL, 0, false},
{kVideoTrackNum, 33, -33, false, NULL, 0, false},
{kAudioTrackNum, 45, -23, false, NULL, 0, false},
{kVideoTrackNum, 66, -34, false, NULL, 0, false},
{kAudioTrackNum, 68, -24, false, NULL, 0, false},
{kVideoTrackNum, 100, -35, false, NULL, 0, false},
};
int block_count1 = arraysize(kBlockInfo1);
@ -1036,8 +1044,10 @@ TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsBlockGroups) {
const int kExpectedAudioEstimationInMs = 24;
const int kExpectedVideoEstimationInMs = 35;
const BlockInfo kBlockInfo2[] = {
{kAudioTrackNum, 92, -kExpectedAudioEstimationInMs, false, NULL, 0},
{kVideoTrackNum, 135, -kExpectedVideoEstimationInMs, false, NULL, 0},
{kAudioTrackNum, 92, -kExpectedAudioEstimationInMs, false, NULL, 0,
false},
{kVideoTrackNum, 135, -kExpectedVideoEstimationInMs, false, NULL, 0,
false},
};
int block_count2 = arraysize(kBlockInfo2);
@ -1056,17 +1066,10 @@ TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsBlockGroups) {
TEST_F(WebMClusterParserTest,
ParseDegenerateClusterYieldsHardcodedEstimatedDurations) {
const BlockInfo kBlockInfo[] = {
{
kAudioTrackNum,
0,
WebMClusterParser::kDefaultAudioBufferDurationInMs,
true
}, {
kVideoTrackNum,
0,
WebMClusterParser::kDefaultVideoBufferDurationInMs,
true
},
{kAudioTrackNum, 0, WebMClusterParser::kDefaultAudioBufferDurationInMs,
true, NULL, 0, false},
{kVideoTrackNum, 0, WebMClusterParser::kDefaultVideoBufferDurationInMs,
true, NULL, 0, false},
};
int block_count = arraysize(kBlockInfo);
@ -1082,8 +1085,10 @@ TEST_F(WebMClusterParserTest,
ResetParserToHaveDefaultDurations();
const BlockInfo kBlockInfo[] = {
{ kAudioTrackNum, 0, kTestAudioFrameDefaultDurationInMs, true },
{ kVideoTrackNum, 0, kTestVideoFrameDefaultDurationInMs, true },
{kAudioTrackNum, 0, kTestAudioFrameDefaultDurationInMs, true, NULL, 0,
false},
{kVideoTrackNum, 0, kTestVideoFrameDefaultDurationInMs, true, NULL, 0,
false},
};
int block_count = arraysize(kBlockInfo);

Binary file not shown.