15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/formats/webm/tracks_builder.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/logging.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/formats/webm/webm_constants.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace media {
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Returns size of an integer, formatted using Matroska serialization.
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int GetUIntMkvSize(uint64 value) {
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value < 0x07FULL)
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 1;
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value < 0x03FFFULL)
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 2;
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value < 0x01FFFFFULL)
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 3;
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value < 0x0FFFFFFFULL)
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 4;
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value < 0x07FFFFFFFFULL)
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 5;
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value < 0x03FFFFFFFFFFULL)
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 6;
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value < 0x01FFFFFFFFFFFFULL)
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 7;
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return 8;
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Returns the minimium size required to serialize an integer value.
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int GetUIntSize(uint64 value) {
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value < 0x0100ULL)
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 1;
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value < 0x010000ULL)
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 2;
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value < 0x01000000ULL)
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 3;
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value < 0x0100000000ULL)
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 4;
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value < 0x010000000000ULL)
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 5;
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value < 0x01000000000000ULL)
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 6;
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value < 0x0100000000000000ULL)
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 7;
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return 8;
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int MasterElementSize(int element_id, int payload_size) {
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return GetUIntSize(element_id) + GetUIntMkvSize(payload_size) + payload_size;
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int UIntElementSize(int element_id, uint64 value) {
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return GetUIntSize(element_id) + 1 + GetUIntSize(value);
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
58effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic int DoubleElementSize(int element_id) {
59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return GetUIntSize(element_id) + 1 + 8;
60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int StringElementSize(int element_id, const std::string& value) {
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetUIntSize(element_id) +
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        GetUIntMkvSize(value.length()) +
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        value.length();
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static void SerializeInt(uint8** buf_ptr, int* buf_size_ptr,
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         int64 value, int size) {
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  uint8*& buf = *buf_ptr;
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int& buf_size = *buf_size_ptr;
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (int idx = 1; idx <= size; ++idx) {
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *buf++ = static_cast<uint8>(value >> ((size - idx) * 8));
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    --buf_size;
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic void SerializeDouble(uint8** buf_ptr, int* buf_size_ptr,
80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            double value) {
81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Use a union to convert |value| to native endian integer bit pattern.
82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  union {
83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    double src;
84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    int64 dst;
85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  } tmp;
86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  tmp.src = value;
87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Write the bytes from native endian |tmp.dst| to big-endian form in |buf|.
89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  SerializeInt(buf_ptr, buf_size_ptr, tmp.dst, 8);
90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static void WriteElementId(uint8** buf, int* buf_size, int element_id) {
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SerializeInt(buf, buf_size, element_id, GetUIntSize(element_id));
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static void WriteUInt(uint8** buf, int* buf_size, uint64 value) {
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const int size = GetUIntMkvSize(value);
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  value |= (1ULL << (size * 7));  // Matroska formatting
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SerializeInt(buf, buf_size, value, size);
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static void WriteMasterElement(uint8** buf, int* buf_size,
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               int element_id, int payload_size) {
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WriteElementId(buf, buf_size, element_id);
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WriteUInt(buf, buf_size, payload_size);
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void WriteUIntElement(uint8** buf,
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             int* buf_size,
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             int element_id,
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             uint64 value) {
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WriteElementId(buf, buf_size, element_id);
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const int size = GetUIntSize(value);
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WriteUInt(buf, buf_size, size);
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SerializeInt(buf, buf_size, value, size);
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic void WriteDoubleElement(uint8** buf, int* buf_size,
121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                               int element_id, double value) {
122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  WriteElementId(buf, buf_size, element_id);
123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  WriteUInt(buf, buf_size, 8);
124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  SerializeDouble(buf, buf_size, value);
125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static void WriteStringElement(uint8** buf_ptr, int* buf_size_ptr,
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               int element_id, const std::string& value) {
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  uint8*& buf = *buf_ptr;
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int& buf_size = *buf_size_ptr;
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WriteElementId(&buf, &buf_size, element_id);
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const uint64 size = value.length();
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WriteUInt(&buf, &buf_size, size);
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  memcpy(buf, value.data(), size);
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  buf += size;
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  buf_size -= size;
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
142effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochTracksBuilder::TracksBuilder(bool allow_invalid_values)
143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    : allow_invalid_values_(allow_invalid_values) {}
144effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochTracksBuilder::TracksBuilder()
145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    : allow_invalid_values_(false) {}
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TracksBuilder::~TracksBuilder() {}
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TracksBuilder::AddVideoTrack(int track_num,
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  uint64 track_uid,
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  const std::string& codec_id,
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  const std::string& name,
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  const std::string& language,
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  int default_duration,
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  int video_pixel_width,
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  int video_pixel_height) {
156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  AddTrackInternal(track_num, kWebMTrackTypeVideo, track_uid, codec_id, name,
157effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   language, default_duration, video_pixel_width,
158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   video_pixel_height, -1, -1);
159effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
160effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TracksBuilder::AddAudioTrack(int track_num,
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  uint64 track_uid,
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  const std::string& codec_id,
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  const std::string& name,
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  const std::string& language,
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  int default_duration,
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  int audio_channels,
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  double audio_sampling_frequency) {
169effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  AddTrackInternal(track_num, kWebMTrackTypeAudio, track_uid, codec_id, name,
170effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   language, default_duration, -1, -1, audio_channels,
171effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   audio_sampling_frequency);
172effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
173effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TracksBuilder::AddTextTrack(int track_num,
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 uint64 track_uid,
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 const std::string& codec_id,
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 const std::string& name,
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 const std::string& language) {
179effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  AddTrackInternal(track_num, kWebMTrackTypeSubtitlesOrCaptions, track_uid,
180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   codec_id, name, language, -1, -1, -1, -1, -1);
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::vector<uint8> TracksBuilder::Finish() {
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Allocate the storage
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<uint8> buffer;
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  buffer.resize(GetTracksSize());
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Populate the storage with a tracks header
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WriteTracks(&buffer[0], buffer.size());
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return buffer;
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TracksBuilder::AddTrackInternal(int track_num,
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     int track_type,
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     uint64 track_uid,
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     const std::string& codec_id,
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     const std::string& name,
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     const std::string& language,
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     int default_duration,
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     int video_pixel_width,
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     int video_pixel_height,
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     int audio_channels,
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     double audio_sampling_frequency) {
205effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  tracks_.push_back(Track(track_num, track_type, track_uid, codec_id, name,
206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                          language, default_duration, video_pixel_width,
207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                          video_pixel_height, audio_channels,
208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                          audio_sampling_frequency, allow_invalid_values_));
209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int TracksBuilder::GetTracksSize() const {
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return MasterElementSize(kWebMIdTracks, GetTracksPayloadSize());
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int TracksBuilder::GetTracksPayloadSize() const {
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int payload_size = 0;
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (TrackList::const_iterator itr = tracks_.begin();
21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       itr != tracks_.end(); ++itr) {
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    payload_size += itr->GetSize();
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return payload_size;
22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void TracksBuilder::WriteTracks(uint8* buf, int buf_size) const {
22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WriteMasterElement(&buf, &buf_size, kWebMIdTracks, GetTracksPayloadSize());
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (TrackList::const_iterator itr = tracks_.begin();
23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       itr != tracks_.end(); ++itr) {
23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    itr->Write(&buf, &buf_size);
23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TracksBuilder::Track::Track(int track_num,
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            int track_type,
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            uint64 track_uid,
23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            const std::string& codec_id,
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            const std::string& name,
240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            const std::string& language,
241effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            int default_duration,
2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            int video_pixel_width,
2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            int video_pixel_height,
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            int audio_channels,
2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            double audio_sampling_frequency,
246effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            bool allow_invalid_values)
24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : track_num_(track_num),
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      track_type_(track_type),
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      track_uid_(track_uid),
25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      codec_id_(codec_id),
25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      name_(name),
252effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      language_(language),
253effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      default_duration_(default_duration),
254effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      video_pixel_width_(video_pixel_width),
255effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      video_pixel_height_(video_pixel_height),
256effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      audio_channels_(audio_channels),
257effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      audio_sampling_frequency_(audio_sampling_frequency) {
258effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!allow_invalid_values) {
259effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    CHECK_GT(track_num_, 0);
260effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    CHECK_GT(track_type_, 0);
261effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    CHECK_LT(track_type_, 255);
262effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    CHECK_GT(track_uid_, 0);
263effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (track_type != kWebMTrackTypeVideo &&
264effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        track_type != kWebMTrackTypeAudio) {
265effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      CHECK_EQ(default_duration_, -1);
266effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    } else {
267effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      CHECK(default_duration_ == -1 || default_duration_ > 0);
268effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
269effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
270effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (track_type == kWebMTrackTypeVideo) {
271effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      CHECK_GT(video_pixel_width_, 0);
272effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      CHECK_GT(video_pixel_height_, 0);
273effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    } else {
274effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      CHECK_EQ(video_pixel_width_, -1);
275effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      CHECK_EQ(video_pixel_height_, -1);
276effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
277effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
278effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (track_type == kWebMTrackTypeAudio) {
279effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      CHECK_GT(audio_channels_, 0);
280effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      CHECK_GT(audio_sampling_frequency_, 0.0);
281effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    } else {
282effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      CHECK_EQ(audio_channels_, -1);
283effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      CHECK_EQ(audio_sampling_frequency_, -1.0);
284effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
285effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int TracksBuilder::Track::GetSize() const {
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return MasterElementSize(kWebMIdTrackEntry, GetPayloadSize());
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
292effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochint TracksBuilder::Track::GetVideoPayloadSize() const {
293effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  int payload_size = 0;
294effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
295effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (video_pixel_width_ >= 0)
2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    payload_size += UIntElementSize(kWebMIdPixelWidth, video_pixel_width_);
297effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (video_pixel_height_ >= 0)
2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    payload_size += UIntElementSize(kWebMIdPixelHeight, video_pixel_height_);
299effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
300effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return payload_size;
301effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
302effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
303effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochint TracksBuilder::Track::GetAudioPayloadSize() const {
304effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  int payload_size = 0;
305effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
306effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (audio_channels_ >= 0)
3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    payload_size += UIntElementSize(kWebMIdChannels, audio_channels_);
308effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (audio_sampling_frequency_ >= 0)
309effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    payload_size += DoubleElementSize(kWebMIdSamplingFrequency);
310effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
311effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return payload_size;
312effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
313effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int TracksBuilder::Track::GetPayloadSize() const {
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int size = 0;
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size += UIntElementSize(kWebMIdTrackNumber, track_num_);
3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size += UIntElementSize(kWebMIdTrackType, track_type_);
3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size += UIntElementSize(kWebMIdTrackUID, track_uid_);
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
321effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (default_duration_ >= 0)
3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size += UIntElementSize(kWebMIdDefaultDuration, default_duration_);
323effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!codec_id_.empty())
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size += StringElementSize(kWebMIdCodecID, codec_id_);
32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!name_.empty())
32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size += StringElementSize(kWebMIdName, name_);
32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!language_.empty())
33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size += StringElementSize(kWebMIdLanguage, language_);
33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
333effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (GetVideoPayloadSize() > 0) {
334effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    size += MasterElementSize(kWebMIdVideo, GetVideoPayloadSize());
335effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
336effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
337effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (GetAudioPayloadSize() > 0) {
338effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    size += MasterElementSize(kWebMIdAudio, GetAudioPayloadSize());
339effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
340effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return size;
34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void TracksBuilder::Track::Write(uint8** buf, int* buf_size) const {
34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WriteMasterElement(buf, buf_size, kWebMIdTrackEntry, GetPayloadSize());
34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WriteUIntElement(buf, buf_size, kWebMIdTrackNumber, track_num_);
3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WriteUIntElement(buf, buf_size, kWebMIdTrackType, track_type_);
3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WriteUIntElement(buf, buf_size, kWebMIdTrackUID, track_uid_);
35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
351effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (default_duration_ >= 0)
3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WriteUIntElement(buf, buf_size, kWebMIdDefaultDuration, default_duration_);
353effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!codec_id_.empty())
35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    WriteStringElement(buf, buf_size, kWebMIdCodecID, codec_id_);
35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!name_.empty())
35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    WriteStringElement(buf, buf_size, kWebMIdName, name_);
35990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!language_.empty())
36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    WriteStringElement(buf, buf_size, kWebMIdLanguage, language_);
362effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
363effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (GetVideoPayloadSize() > 0) {
364effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    WriteMasterElement(buf, buf_size, kWebMIdVideo, GetVideoPayloadSize());
365effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
366effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (video_pixel_width_ >= 0)
3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      WriteUIntElement(buf, buf_size, kWebMIdPixelWidth, video_pixel_width_);
368effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
369effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (video_pixel_height_ >= 0)
3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      WriteUIntElement(buf, buf_size, kWebMIdPixelHeight, video_pixel_height_);
371effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
372effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
373effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (GetAudioPayloadSize() > 0) {
374effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    WriteMasterElement(buf, buf_size, kWebMIdAudio, GetAudioPayloadSize());
375effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
376effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (audio_channels_ >= 0)
3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      WriteUIntElement(buf, buf_size, kWebMIdChannels, audio_channels_);
378effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
379effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (audio_sampling_frequency_ >= 0) {
380effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      WriteDoubleElement(buf, buf_size, kWebMIdSamplingFrequency,
381effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          audio_sampling_frequency_);
382effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
383effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace media
387