15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/webm/webm_cluster_parser.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/sys_byteorder.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/buffers.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/decrypt_config.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/filters/webvtt_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/webm/webm_constants.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/webm/webm_crypto_helpers.h"
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/webm/webm_webvtt_parser.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebMClusterParser::TextTrackIterator::TextTrackIterator(
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const TextTrackMap& text_track_map) :
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    iterator_(text_track_map.begin()),
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    iterator_end_(text_track_map.end()) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebMClusterParser::TextTrackIterator::TextTrackIterator(
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const TextTrackIterator& rhs) :
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    iterator_(rhs.iterator_),
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    iterator_end_(rhs.iterator_end_) {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebMClusterParser::TextTrackIterator::~TextTrackIterator() {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WebMClusterParser::TextTrackIterator::operator()(
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int* track_num,
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const BufferQueue** buffers) {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iterator_ == iterator_end_) {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *track_num = 0;
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *buffers = NULL;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *track_num = iterator_->first;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *buffers = &iterator_->second.buffers();
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ++iterator_;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebMClusterParser::WebMClusterParser(
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 timecode_scale, int audio_track_num, int video_track_num,
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const WebMTracksParser::TextTracks& text_tracks,
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::set<int64>& ignored_tracks,
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& audio_encryption_key_id,
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& video_encryption_key_id,
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const LogCB& log_cb)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : timecode_multiplier_(timecode_scale / 1000.0),
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ignored_tracks_(ignored_tracks),
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      audio_encryption_key_id_(audio_encryption_key_id),
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      video_encryption_key_id_(video_encryption_key_id),
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parser_(kWebMIdCluster, this),
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_block_timecode_(-1),
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      block_data_size_(-1),
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      block_duration_(-1),
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      block_add_id_(-1),
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      block_additional_data_size_(-1),
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      discard_padding_(-1),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cluster_timecode_(-1),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cluster_start_time_(kNoTimestamp()),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cluster_ended_(false),
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      audio_(audio_track_num, false),
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      video_(video_track_num, true),
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      log_cb_(log_cb) {
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (WebMTracksParser::TextTracks::const_iterator it = text_tracks.begin();
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != text_tracks.end();
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++it) {
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    text_track_map_.insert(std::make_pair(it->first, Track(it->first, false)));
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebMClusterParser::~WebMClusterParser() {}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebMClusterParser::Reset() {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_block_timecode_ = -1;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cluster_timecode_ = -1;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cluster_start_time_ = kNoTimestamp();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cluster_ended_ = false;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser_.Reset();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_.Reset();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  video_.Reset();
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResetTextTracks();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int WebMClusterParser::Parse(const uint8* buf, int size) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_.Reset();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  video_.Reset();
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResetTextTracks();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = parser_.Parse(buf, size);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cluster_ended_ = false;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cluster_ended_ = parser_.IsParsingComplete();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cluster_ended_) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If there were no buffers in this cluster, set the cluster start time to
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // be the |cluster_timecode_|.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cluster_start_time_ == kNoTimestamp()) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_GT(cluster_timecode_, -1);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cluster_start_time_ = base::TimeDelta::FromMicroseconds(
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cluster_timecode_ * timecode_multiplier_);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Reset the parser if we're done parsing so that
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // it is ready to accept another cluster on the next
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // call.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parser_.Reset();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_block_timecode_ = -1;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cluster_timecode_ = -1;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebMClusterParser::TextTrackIterator
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebMClusterParser::CreateTextTrackIterator() const {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return TextTrackIterator(text_track_map_);
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebMParserClient* WebMClusterParser::OnListStart(int id) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id == kWebMIdCluster) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cluster_timecode_ = -1;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cluster_start_time_ = kNoTimestamp();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (id == kWebMIdBlockGroup) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    block_data_.reset();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    block_data_size_ = -1;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    block_duration_ = -1;
14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    discard_padding_ = -1;
14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    discard_padding_set_ = false;
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else if (id == kWebMIdBlockAdditions) {
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    block_add_id_ = -1;
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    block_additional_data_.reset();
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    block_additional_data_size_ = -1;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return this;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebMClusterParser::OnListEnd(int id) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id != kWebMIdBlockGroup)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure the BlockGroup actually had a Block.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (block_data_size_ == -1) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MEDIA_LOG(log_cb_) << "Block missing from BlockGroup.";
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool result = ParseBlock(false, block_data_.get(), block_data_size_,
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                           block_additional_data_.get(),
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           block_additional_data_size_, block_duration_,
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           discard_padding_set_ ? discard_padding_ : 0);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  block_data_.reset();
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  block_data_size_ = -1;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  block_duration_ = -1;
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  block_add_id_ = -1;
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  block_additional_data_.reset();
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  block_additional_data_size_ = -1;
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  discard_padding_ = -1;
17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  discard_padding_set_ = false;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebMClusterParser::OnUInt(int id, int64 val) {
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int64* dst;
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (id) {
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kWebMIdTimecode:
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      dst = &cluster_timecode_;
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kWebMIdBlockDuration:
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      dst = &block_duration_;
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kWebMIdBlockAddID:
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      dst = &block_add_id_;
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case kWebMIdDiscardPadding:
19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (discard_padding_set_)
19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        return false;
19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      discard_padding_set_ = true;
19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      discard_padding_ = val;
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return true;
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (*dst != -1)
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *dst = val;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WebMClusterParser::ParseBlock(bool is_simple_block, const uint8* buf,
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                   int size, const uint8* additional,
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   int additional_size, int duration,
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   int64 discard_padding) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size < 4)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return an error if the trackNum > 127. We just aren't
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // going to support large track numbers right now.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(buf[0] & 0x80)) {
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MEDIA_LOG(log_cb_) << "TrackNumber over 127 not supported";
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int track_num = buf[0] & 0x7f;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int timecode = buf[1] << 8 | buf[2];
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = buf[3] & 0xff;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int lacing = (flags >> 1) & 0x3;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (lacing) {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MEDIA_LOG(log_cb_) << "Lacing " << lacing << " is not supported yet.";
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sign extend negative timecode offsets.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (timecode & 0x8000)
2323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    timecode |= ~0xffff;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8* frame_data = buf + 4;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int frame_size = size - (frame_data - buf);
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return OnBlock(is_simple_block, track_num, timecode, duration, flags,
23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                 frame_data, frame_size, additional, additional_size,
23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                 discard_padding);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebMClusterParser::OnBinary(int id, const uint8* data, int size) {
24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (id) {
24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kWebMIdSimpleBlock:
24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return ParseBlock(true, data, size, NULL, -1, -1, 0);
24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kWebMIdBlock:
24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (block_data_) {
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        MEDIA_LOG(log_cb_) << "More than 1 Block in a BlockGroup is not "
24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              "supported.";
25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return false;
25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      block_data_.reset(new uint8[size]);
25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      memcpy(block_data_.get(), data, size);
25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      block_data_size_ = size;
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kWebMIdBlockAdditional: {
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      uint64 block_add_id = base::HostToNet64(block_add_id_);
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (block_additional_data_) {
26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // TODO(vigneshv): Technically, more than 1 BlockAdditional is allowed
26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // as per matroska spec. But for now we don't have a use case to
26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // support parsing of such files. Take a look at this again when such a
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // case arises.
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        MEDIA_LOG(log_cb_) << "More than 1 BlockAdditional in a BlockGroup is "
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              "not supported.";
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return false;
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // First 8 bytes of side_data in DecoderBuffer is the BlockAddID
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // element's value in Big Endian format. This is done to mimic ffmpeg
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // demuxer's behavior.
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      block_additional_data_size_ = size + sizeof(block_add_id);
27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      block_additional_data_.reset(new uint8[block_additional_data_size_]);
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      memcpy(block_additional_data_.get(), &block_add_id,
27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)             sizeof(block_add_id));
27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      memcpy(block_additional_data_.get() + 8, data, size);
27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WebMClusterParser::OnBlock(bool is_simple_block, int track_num,
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                int timecode,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int  block_duration,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int flags,
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                const uint8* data, int size,
28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                const uint8* additional, int additional_size,
29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                int64 discard_padding) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(size, 0);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cluster_timecode_ == -1) {
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MEDIA_LOG(log_cb_) << "Got a block before cluster timecode.";
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // TODO(acolwell): Should relative negative timecode offsets be rejected?  Or
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // only when the absolute timecode is negative?  See http://crbug.com/271794
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (timecode < 0) {
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MEDIA_LOG(log_cb_) << "Got a block with negative timecode offset "
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       << timecode;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_block_timecode_ != -1 && timecode < last_block_timecode_) {
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MEDIA_LOG(log_cb_)
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        << "Got a block with a timecode before the previous block.";
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Track* track = NULL;
312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool is_text = false;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string encryption_key_id;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (track_num == audio_.track_num()) {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    track = &audio_;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    encryption_key_id = audio_encryption_key_id_;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (track_num == video_.track_num()) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    track = &video_;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    encryption_key_id = video_encryption_key_id_;
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (ignored_tracks_.find(track_num) != ignored_tracks_.end()) {
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (Track* const text_track = FindTextTrack(track_num)) {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (is_simple_block)  // BlockGroup is required for WebVTT cues
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (block_duration < 0)  // not specified
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    track = text_track;
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    is_text = true;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MEDIA_LOG(log_cb_) << "Unexpected track number " << track_num;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_block_timecode_ = timecode;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (cluster_timecode_ + timecode) * timecode_multiplier_);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The first bit of the flags is set when a SimpleBlock contains only
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // keyframes. If this is a Block, then inspection of the payload is
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // necessary to determine whether it contains a keyframe or not.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://www.matroska.org/technical/specs/index.html
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_keyframe =
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_simple_block ? (flags & 0x80) != 0 : track->IsKeyframe(data, size);
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_refptr<StreamParserBuffer> buffer;
347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!is_text) {
348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    buffer = StreamParserBuffer::CopyFrom(data, size,
349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                          additional, additional_size,
350f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                          is_keyframe);
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    std::string id, settings, content;
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    WebMWebVTTParser::Parse(data, size,
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            &id, &settings, &content);
355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    std::vector<uint8> side_data;
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    MakeSideData(id.begin(), id.end(),
358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 settings.begin(), settings.end(),
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 &side_data);
360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    buffer = StreamParserBuffer::CopyFrom(
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        reinterpret_cast<const uint8*>(content.data()),
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        content.length(),
364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        &side_data[0],
365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        side_data.size(),
366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        is_keyframe);
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Every encrypted Block has a signal byte and IV prepended to it. Current
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // encrypted WebM request for comments specification is here
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://wiki.webmproject.org/encryption/webm-encryption-rfc
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!encryption_key_id.empty()) {
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<DecryptConfig> config(WebMCreateDecryptConfig(
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        data, size,
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        reinterpret_cast<const uint8*>(encryption_key_id.data()),
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        encryption_key_id.size()));
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!config)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
379ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    buffer->set_decrypt_config(config.Pass());
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
382ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  buffer->set_timestamp(timestamp);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cluster_start_time_ == kNoTimestamp())
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cluster_start_time_ = timestamp;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (block_duration >= 0) {
387ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    buffer->set_duration(base::TimeDelta::FromMicroseconds(
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        block_duration * timecode_multiplier_));
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (discard_padding != 0) {
39258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    buffer->set_discard_padding(base::TimeDelta::FromMicroseconds(
39358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                    discard_padding / 1000));
39458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
39558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return track->AddBuffer(buffer);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebMClusterParser::Track::Track(int track_num, bool is_video)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : track_num_(track_num),
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_video_(is_video) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebMClusterParser::Track::~Track() {}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebMClusterParser::Track::AddBuffer(
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<StreamParserBuffer>& buffer) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(2) << "AddBuffer() : " << track_num_
409ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch           << " ts " << buffer->timestamp().InSecondsF()
410ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch           << " dur " << buffer->duration().InSecondsF()
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << " kf " << buffer->IsKeyframe()
412ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch           << " size " << buffer->data_size();
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffers_.push_back(buffer);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebMClusterParser::Track::Reset() {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffers_.clear();
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WebMClusterParser::Track::IsKeyframe(const uint8* data, int size) const {
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For now, assume that all blocks are keyframes for datatypes other than
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // video. This is a valid assumption for Vorbis, WebVTT, & Opus.
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!is_video_)
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure the block is big enough for the minimal keyframe header size.
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size < 7)
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The LSb of the first byte must be a 0 for a keyframe.
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // http://tools.ietf.org/html/rfc6386 Section 19.1
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if ((data[0] & 0x01) != 0)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify VP8 keyframe startcode.
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // http://tools.ietf.org/html/rfc6386 Section 19.1
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (data[3] != 0x9d || data[4] != 0x01 || data[5] != 0x2a)
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebMClusterParser::ResetTextTracks() {
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (TextTrackMap::iterator it = text_track_map_.begin();
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != text_track_map_.end();
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++it) {
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    it->second.Reset();
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebMClusterParser::Track*
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebMClusterParser::FindTextTrack(int track_num) {
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const TextTrackMap::iterator it = text_track_map_.find(track_num);
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it == text_track_map_.end())
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return &it->second;
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
464