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:
parent
db92c9a22b
commit
d501b457d0
|
@ -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.
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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_) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
Loading…
Reference in New Issue