1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/webm/tracks_builder.h"
7 #include "media/webm/webm_constants.h"
11 // Returns size of an integer, formatted using Matroska serialization.
12 static int GetUIntMkvSize(uint64 value
) {
15 if (value
< 0x03FFFULL
)
17 if (value
< 0x01FFFFFULL
)
19 if (value
< 0x0FFFFFFFULL
)
21 if (value
< 0x07FFFFFFFFULL
)
23 if (value
< 0x03FFFFFFFFFFULL
)
25 if (value
< 0x01FFFFFFFFFFFFULL
)
30 // Returns the minimium size required to serialize an integer value.
31 static int GetUIntSize(uint64 value
) {
32 if (value
< 0x0100ULL
)
34 if (value
< 0x010000ULL
)
36 if (value
< 0x01000000ULL
)
38 if (value
< 0x0100000000ULL
)
40 if (value
< 0x010000000000ULL
)
42 if (value
< 0x01000000000000ULL
)
44 if (value
< 0x0100000000000000ULL
)
49 static int MasterElementSize(int element_id
, int payload_size
) {
50 return GetUIntSize(element_id
) + GetUIntMkvSize(payload_size
) + payload_size
;
53 static int IntElementSize(int element_id
, int value
) {
54 return GetUIntSize(element_id
) + 1 + GetUIntSize(value
);
57 static int StringElementSize(int element_id
, const std::string
& value
) {
58 return GetUIntSize(element_id
) +
59 GetUIntMkvSize(value
.length()) +
63 static void SerializeInt(uint8
** buf_ptr
, int* buf_size_ptr
,
64 int64 value
, int size
) {
65 uint8
*& buf
= *buf_ptr
;
66 int& buf_size
= *buf_size_ptr
;
68 for (int idx
= 1; idx
<= size
; ++idx
) {
69 *buf
++ = static_cast<uint8
>(value
>> ((size
- idx
) * 8));
74 static void WriteElementId(uint8
** buf
, int* buf_size
, int element_id
) {
75 SerializeInt(buf
, buf_size
, element_id
, GetUIntSize(element_id
));
78 static void WriteUInt(uint8
** buf
, int* buf_size
, uint64 value
) {
79 const int size
= GetUIntMkvSize(value
);
80 value
|= (1ULL << (size
* 7)); // Matroska formatting
81 SerializeInt(buf
, buf_size
, value
, size
);
84 static void WriteMasterElement(uint8
** buf
, int* buf_size
,
85 int element_id
, int payload_size
) {
86 WriteElementId(buf
, buf_size
, element_id
);
87 WriteUInt(buf
, buf_size
, payload_size
);
90 static void WriteIntElement(uint8
** buf
, int* buf_size
,
91 int element_id
, int value
) {
92 WriteElementId(buf
, buf_size
, element_id
);
94 const int size
= GetUIntSize(value
);
95 WriteUInt(buf
, buf_size
, size
);
97 SerializeInt(buf
, buf_size
, value
, size
);
100 static void WriteStringElement(uint8
** buf_ptr
, int* buf_size_ptr
,
101 int element_id
, const std::string
& value
) {
102 uint8
*& buf
= *buf_ptr
;
103 int& buf_size
= *buf_size_ptr
;
105 WriteElementId(&buf
, &buf_size
, element_id
);
107 const uint64 size
= value
.length();
108 WriteUInt(&buf
, &buf_size
, size
);
110 memcpy(buf
, value
.data(), size
);
115 TracksBuilder::TracksBuilder() {}
116 TracksBuilder::~TracksBuilder() {}
118 void TracksBuilder::AddTrack(
122 const std::string
& codec_id
,
123 const std::string
& name
,
124 const std::string
& language
) {
125 tracks_
.push_back(Track(track_num
, track_type
, track_uid
, codec_id
, name
,
129 std::vector
<uint8
> TracksBuilder::Finish() {
130 // Allocate the storage
131 std::vector
<uint8
> buffer
;
132 buffer
.resize(GetTracksSize());
134 // Populate the storage with a tracks header
135 WriteTracks(&buffer
[0], buffer
.size());
140 int TracksBuilder::GetTracksSize() const {
141 return MasterElementSize(kWebMIdTracks
, GetTracksPayloadSize());
144 int TracksBuilder::GetTracksPayloadSize() const {
145 int payload_size
= 0;
147 for (TrackList::const_iterator itr
= tracks_
.begin();
148 itr
!= tracks_
.end(); ++itr
) {
149 payload_size
+= itr
->GetSize();
155 void TracksBuilder::WriteTracks(uint8
* buf
, int buf_size
) const {
156 WriteMasterElement(&buf
, &buf_size
, kWebMIdTracks
, GetTracksPayloadSize());
158 for (TrackList::const_iterator itr
= tracks_
.begin();
159 itr
!= tracks_
.end(); ++itr
) {
160 itr
->Write(&buf
, &buf_size
);
164 TracksBuilder::Track::Track(int track_num
, int track_type
, int track_uid
,
165 const std::string
& codec_id
,
166 const std::string
& name
,
167 const std::string
& language
)
168 : track_num_(track_num
),
169 track_type_(track_type
),
170 track_uid_(track_uid
),
173 language_(language
) {
176 int TracksBuilder::Track::GetSize() const {
177 return MasterElementSize(kWebMIdTrackEntry
, GetPayloadSize());
180 int TracksBuilder::Track::GetPayloadSize() const {
183 size
+= IntElementSize(kWebMIdTrackNumber
, track_num_
);
184 size
+= IntElementSize(kWebMIdTrackType
, track_type_
);
185 size
+= IntElementSize(kWebMIdTrackUID
, track_uid_
);
187 if (!codec_id_
.empty())
188 size
+= StringElementSize(kWebMIdCodecID
, codec_id_
);
191 size
+= StringElementSize(kWebMIdName
, name_
);
193 if (!language_
.empty())
194 size
+= StringElementSize(kWebMIdLanguage
, language_
);
199 void TracksBuilder::Track::Write(uint8
** buf
, int* buf_size
) const {
200 WriteMasterElement(buf
, buf_size
, kWebMIdTrackEntry
, GetPayloadSize());
202 WriteIntElement(buf
, buf_size
, kWebMIdTrackNumber
, track_num_
);
203 WriteIntElement(buf
, buf_size
, kWebMIdTrackType
, track_type_
);
204 WriteIntElement(buf
, buf_size
, kWebMIdTrackUID
, track_uid_
);
206 if (!codec_id_
.empty())
207 WriteStringElement(buf
, buf_size
, kWebMIdCodecID
, codec_id_
);
210 WriteStringElement(buf
, buf_size
, kWebMIdName
, name_
);
212 if (!language_
.empty())
213 WriteStringElement(buf
, buf_size
, kWebMIdLanguage
, language_
);