| Index: media/webm/webm_cluster_parser.cc
|
| diff --git a/media/webm/webm_cluster_parser.cc b/media/webm/webm_cluster_parser.cc
|
| index ec89b67b3a7ec568f8b9944ed7562f783c2cf11c..41e193f88a1ab06f303ecbba461e52022191d78d 100644
|
| --- a/media/webm/webm_cluster_parser.cc
|
| +++ b/media/webm/webm_cluster_parser.cc
|
| @@ -7,6 +7,7 @@
|
| #include <vector>
|
|
|
| #include "base/logging.h"
|
| +#include "base/sys_byteorder.h"
|
| #include "media/base/buffers.h"
|
| #include "media/base/decrypt_config.h"
|
| #include "media/webm/webm_constants.h"
|
| @@ -61,6 +62,8 @@ WebMClusterParser::WebMClusterParser(
|
| last_block_timecode_(-1),
|
| block_data_size_(-1),
|
| block_duration_(-1),
|
| + block_add_id_(-1),
|
| + block_additional_data_size_(-1),
|
| cluster_timecode_(-1),
|
| cluster_start_time_(kNoTimestamp()),
|
| cluster_ended_(false),
|
| @@ -134,6 +137,10 @@ WebMParserClient* WebMClusterParser::OnListStart(int id) {
|
| block_data_.reset();
|
| block_data_size_ = -1;
|
| block_duration_ = -1;
|
| + } else if (id == kWebMIdBlockAdditions) {
|
| + block_add_id_ = -1;
|
| + block_additional_data_.reset();
|
| + block_additional_data_size_ = -1;
|
| }
|
|
|
| return this;
|
| @@ -150,30 +157,41 @@ bool WebMClusterParser::OnListEnd(int id) {
|
| }
|
|
|
| bool result = ParseBlock(false, block_data_.get(), block_data_size_,
|
| - block_duration_);
|
| + block_additional_data_.get(),
|
| + block_additional_data_size_, block_duration_);
|
| block_data_.reset();
|
| block_data_size_ = -1;
|
| block_duration_ = -1;
|
| + block_add_id_ = -1;
|
| + block_additional_data_.reset();
|
| + block_additional_data_size_ = -1;
|
| return result;
|
| }
|
|
|
| bool WebMClusterParser::OnUInt(int id, int64 val) {
|
| - if (id == kWebMIdTimecode) {
|
| - if (cluster_timecode_ != -1)
|
| - return false;
|
| -
|
| - cluster_timecode_ = val;
|
| - } else if (id == kWebMIdBlockDuration) {
|
| - if (block_duration_ != -1)
|
| - return false;
|
| - block_duration_ = val;
|
| + int64* dst;
|
| + switch (id) {
|
| + case kWebMIdTimecode:
|
| + dst = &cluster_timecode_;
|
| + break;
|
| + case kWebMIdBlockDuration:
|
| + dst = &block_duration_;
|
| + break;
|
| + case kWebMIdBlockAddID:
|
| + dst = &block_add_id_;
|
| + break;
|
| + default:
|
| + return true;
|
| }
|
| -
|
| + if (*dst != -1)
|
| + return false;
|
| + *dst = val;
|
| return true;
|
| }
|
|
|
| bool WebMClusterParser::ParseBlock(bool is_simple_block, const uint8* buf,
|
| - int size, int duration) {
|
| + int size, const uint8* additional,
|
| + int additional_size, int duration) {
|
| if (size < 4)
|
| return false;
|
|
|
| @@ -201,32 +219,58 @@ bool WebMClusterParser::ParseBlock(bool is_simple_block, const uint8* buf,
|
| const uint8* 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);
|
| + frame_data, frame_size, additional, additional_size);
|
| }
|
|
|
| bool WebMClusterParser::OnBinary(int id, const uint8* data, int size) {
|
| - if (id == kWebMIdSimpleBlock)
|
| - return ParseBlock(true, data, size, -1);
|
| -
|
| - if (id != kWebMIdBlock)
|
| - return true;
|
| + switch (id) {
|
| + case kWebMIdSimpleBlock:
|
| + return ParseBlock(true, data, size, NULL, -1, -1);
|
| +
|
| + case kWebMIdBlock:
|
| + if (block_data_) {
|
| + MEDIA_LOG(log_cb_) << "More than 1 Block in a BlockGroup is not "
|
| + "supported.";
|
| + return false;
|
| + }
|
| + block_data_.reset(new uint8[size]);
|
| + memcpy(block_data_.get(), data, size);
|
| + block_data_size_ = size;
|
| + return true;
|
| +
|
| + case kWebMIdBlockAdditional: {
|
| + uint64 block_add_id = base::HostToNet64(block_add_id_);
|
| + if (block_additional_data_) {
|
| + // TODO(vigneshv): Technically, more than 1 BlockAdditional is allowed
|
| + // 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
|
| + // case arises.
|
| + MEDIA_LOG(log_cb_) << "More than 1 BlockAdditional in a BlockGroup is "
|
| + "not supported.";
|
| + return false;
|
| + }
|
| + // First 8 bytes of side_data in DecoderBuffer is the BlockAddID
|
| + // element's value in Big Endian format. This is done to mimic ffmpeg
|
| + // demuxer's behavior.
|
| + block_additional_data_size_ = size + sizeof(block_add_id);
|
| + block_additional_data_.reset(new uint8[block_additional_data_size_]);
|
| + memcpy(block_additional_data_.get(), &block_add_id,
|
| + sizeof(block_add_id));
|
| + memcpy(block_additional_data_.get() + 8, data, size);
|
| + return true;
|
| + }
|
|
|
| - if (block_data_) {
|
| - MEDIA_LOG(log_cb_) << "More than 1 Block in a BlockGroup is not supported.";
|
| - return false;
|
| + default:
|
| + return true;
|
| }
|
| -
|
| - block_data_.reset(new uint8[size]);
|
| - memcpy(block_data_.get(), data, size);
|
| - block_data_size_ = size;
|
| - return true;
|
| }
|
|
|
| bool WebMClusterParser::OnBlock(bool is_simple_block, int track_num,
|
| int timecode,
|
| int block_duration,
|
| int flags,
|
| - const uint8* data, int size) {
|
| + const uint8* data, int size,
|
| + const uint8* additional, int additional_size) {
|
| DCHECK_GE(size, 0);
|
| if (cluster_timecode_ == -1) {
|
| MEDIA_LOG(log_cb_) << "Got a block before cluster timecode.";
|
| @@ -279,7 +323,8 @@ bool WebMClusterParser::OnBlock(bool is_simple_block, int track_num,
|
| is_simple_block ? (flags & 0x80) != 0 : track->IsKeyframe(data, size);
|
|
|
| scoped_refptr<StreamParserBuffer> buffer =
|
| - StreamParserBuffer::CopyFrom(data, size, is_keyframe);
|
| + StreamParserBuffer::CopyFrom(data, size, additional, additional_size,
|
| + is_keyframe);
|
|
|
| // Every encrypted Block has a signal byte and IV prepended to it. Current
|
| // encrypted WebM request for comments specification is here
|
|
|