| Index: media/formats/webm/tracks_builder.cc
|
| diff --git a/media/formats/webm/tracks_builder.cc b/media/formats/webm/tracks_builder.cc
|
| index 5a49ce05f4f49b6a2b8fdd4dbd593a8ddd33057e..fb402c4729c7f478c002273b1a7952233ef540ff 100644
|
| --- a/media/formats/webm/tracks_builder.cc
|
| +++ b/media/formats/webm/tracks_builder.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "media/formats/webm/tracks_builder.h"
|
|
|
| +#include "base/logging.h"
|
| #include "media/formats/webm/webm_constants.h"
|
|
|
| namespace media {
|
| @@ -54,6 +55,10 @@ static int IntElementSize(int element_id, int value) {
|
| return GetUIntSize(element_id) + 1 + GetUIntSize(value);
|
| }
|
|
|
| +static int DoubleElementSize(int element_id) {
|
| + return GetUIntSize(element_id) + 1 + 8;
|
| +}
|
| +
|
| static int StringElementSize(int element_id, const std::string& value) {
|
| return GetUIntSize(element_id) +
|
| GetUIntMkvSize(value.length()) +
|
| @@ -71,6 +76,19 @@ static void SerializeInt(uint8** buf_ptr, int* buf_size_ptr,
|
| }
|
| }
|
|
|
| +static void SerializeDouble(uint8** buf_ptr, int* buf_size_ptr,
|
| + double value) {
|
| + // Use a union to convert |value| to native endian integer bit pattern.
|
| + union {
|
| + double src;
|
| + int64 dst;
|
| + } tmp;
|
| + tmp.src = value;
|
| +
|
| + // Write the bytes from native endian |tmp.dst| to big-endian form in |buf|.
|
| + SerializeInt(buf_ptr, buf_size_ptr, tmp.dst, 8);
|
| +}
|
| +
|
| static void WriteElementId(uint8** buf, int* buf_size, int element_id) {
|
| SerializeInt(buf, buf_size, element_id, GetUIntSize(element_id));
|
| }
|
| @@ -97,6 +115,13 @@ static void WriteIntElement(uint8** buf, int* buf_size,
|
| SerializeInt(buf, buf_size, value, size);
|
| }
|
|
|
| +static void WriteDoubleElement(uint8** buf, int* buf_size,
|
| + int element_id, double value) {
|
| + WriteElementId(buf, buf_size, element_id);
|
| + WriteUInt(buf, buf_size, 8);
|
| + SerializeDouble(buf, buf_size, value);
|
| +}
|
| +
|
| static void WriteStringElement(uint8** buf_ptr, int* buf_size_ptr,
|
| int element_id, const std::string& value) {
|
| uint8*& buf = *buf_ptr;
|
| @@ -112,18 +137,48 @@ static void WriteStringElement(uint8** buf_ptr, int* buf_size_ptr,
|
| buf_size -= size;
|
| }
|
|
|
| -TracksBuilder::TracksBuilder() {}
|
| +TracksBuilder::TracksBuilder(bool allow_invalid_values)
|
| + : allow_invalid_values_(allow_invalid_values) {}
|
| +TracksBuilder::TracksBuilder()
|
| + : allow_invalid_values_(false) {}
|
| TracksBuilder::~TracksBuilder() {}
|
|
|
| -void TracksBuilder::AddTrack(
|
| +void TracksBuilder::AddVideoTrack(
|
| + int track_num,
|
| + int track_uid,
|
| + const std::string& codec_id,
|
| + const std::string& name,
|
| + const std::string& language,
|
| + int default_duration,
|
| + int video_pixel_width,
|
| + int video_pixel_height) {
|
| + AddTrackInternal(track_num, kWebMTrackTypeVideo, track_uid, codec_id, name,
|
| + language, default_duration, video_pixel_width,
|
| + video_pixel_height, -1, -1);
|
| +}
|
| +
|
| +void TracksBuilder::AddAudioTrack(
|
| + int track_num,
|
| + int track_uid,
|
| + const std::string& codec_id,
|
| + const std::string& name,
|
| + const std::string& language,
|
| + int default_duration,
|
| + int audio_channels,
|
| + double audio_sampling_frequency) {
|
| + AddTrackInternal(track_num, kWebMTrackTypeAudio, track_uid, codec_id, name,
|
| + language, default_duration, -1, -1, audio_channels,
|
| + audio_sampling_frequency);
|
| +}
|
| +
|
| +void TracksBuilder::AddTextTrack(
|
| int track_num,
|
| - int track_type,
|
| int track_uid,
|
| const std::string& codec_id,
|
| const std::string& name,
|
| const std::string& language) {
|
| - tracks_.push_back(Track(track_num, track_type, track_uid, codec_id, name,
|
| - language));
|
| + AddTrackInternal(track_num, kWebMTrackTypeSubtitlesOrCaptions, track_uid,
|
| + codec_id, name, language, -1, -1, -1, -1, -1);
|
| }
|
|
|
| std::vector<uint8> TracksBuilder::Finish() {
|
| @@ -137,6 +192,24 @@ std::vector<uint8> TracksBuilder::Finish() {
|
| return buffer;
|
| }
|
|
|
| +void TracksBuilder::AddTrackInternal(
|
| + int track_num,
|
| + int track_type,
|
| + int track_uid,
|
| + const std::string& codec_id,
|
| + const std::string& name,
|
| + const std::string& language,
|
| + int default_duration,
|
| + int video_pixel_width,
|
| + int video_pixel_height,
|
| + int audio_channels,
|
| + double audio_sampling_frequency) {
|
| + tracks_.push_back(Track(track_num, track_type, track_uid, codec_id, name,
|
| + language, default_duration, video_pixel_width,
|
| + video_pixel_height, audio_channels,
|
| + audio_sampling_frequency, allow_invalid_values_));
|
| +}
|
| +
|
| int TracksBuilder::GetTracksSize() const {
|
| return MasterElementSize(kWebMIdTracks, GetTracksPayloadSize());
|
| }
|
| @@ -164,19 +237,78 @@ void TracksBuilder::WriteTracks(uint8* buf, int buf_size) const {
|
| TracksBuilder::Track::Track(int track_num, int track_type, int track_uid,
|
| const std::string& codec_id,
|
| const std::string& name,
|
| - const std::string& language)
|
| + const std::string& language,
|
| + int default_duration,
|
| + int video_pixel_width, int video_pixel_height,
|
| + int audio_channels, double audio_sampling_frequency,
|
| + bool allow_invalid_values)
|
| : track_num_(track_num),
|
| track_type_(track_type),
|
| track_uid_(track_uid),
|
| codec_id_(codec_id),
|
| name_(name),
|
| - language_(language) {
|
| + language_(language),
|
| + default_duration_(default_duration),
|
| + video_pixel_width_(video_pixel_width),
|
| + video_pixel_height_(video_pixel_height),
|
| + audio_channels_(audio_channels),
|
| + audio_sampling_frequency_(audio_sampling_frequency) {
|
| + if (!allow_invalid_values) {
|
| + CHECK_GT(track_num_, 0);
|
| + CHECK_GT(track_type_, 0);
|
| + CHECK_LT(track_type_, 255);
|
| + CHECK_GT(track_uid_, 0);
|
| + if (track_type != kWebMTrackTypeVideo &&
|
| + track_type != kWebMTrackTypeAudio) {
|
| + CHECK_EQ(default_duration_, -1);
|
| + } else {
|
| + CHECK(default_duration_ == -1 || default_duration_ > 0);
|
| + }
|
| +
|
| + if (track_type == kWebMTrackTypeVideo) {
|
| + CHECK_GT(video_pixel_width_, 0);
|
| + CHECK_GT(video_pixel_height_, 0);
|
| + } else {
|
| + CHECK_EQ(video_pixel_width_, -1);
|
| + CHECK_EQ(video_pixel_height_, -1);
|
| + }
|
| +
|
| + if (track_type == kWebMTrackTypeAudio) {
|
| + CHECK_GT(audio_channels_, 0);
|
| + CHECK_GT(audio_sampling_frequency_, 0.0);
|
| + } else {
|
| + CHECK_EQ(audio_channels_, -1);
|
| + CHECK_EQ(audio_sampling_frequency_, -1.0);
|
| + }
|
| + }
|
| }
|
|
|
| int TracksBuilder::Track::GetSize() const {
|
| return MasterElementSize(kWebMIdTrackEntry, GetPayloadSize());
|
| }
|
|
|
| +int TracksBuilder::Track::GetVideoPayloadSize() const {
|
| + int payload_size = 0;
|
| +
|
| + if (video_pixel_width_ >= 0)
|
| + payload_size += IntElementSize(kWebMIdPixelWidth, video_pixel_width_);
|
| + if (video_pixel_height_ >= 0)
|
| + payload_size += IntElementSize(kWebMIdPixelHeight, video_pixel_height_);
|
| +
|
| + return payload_size;
|
| +}
|
| +
|
| +int TracksBuilder::Track::GetAudioPayloadSize() const {
|
| + int payload_size = 0;
|
| +
|
| + if (audio_channels_ >= 0)
|
| + payload_size += IntElementSize(kWebMIdChannels, audio_channels_);
|
| + if (audio_sampling_frequency_ >= 0)
|
| + payload_size += DoubleElementSize(kWebMIdSamplingFrequency);
|
| +
|
| + return payload_size;
|
| +}
|
| +
|
| int TracksBuilder::Track::GetPayloadSize() const {
|
| int size = 0;
|
|
|
| @@ -184,6 +316,9 @@ int TracksBuilder::Track::GetPayloadSize() const {
|
| size += IntElementSize(kWebMIdTrackType, track_type_);
|
| size += IntElementSize(kWebMIdTrackUID, track_uid_);
|
|
|
| + if (default_duration_ >= 0)
|
| + size += IntElementSize(kWebMIdDefaultDuration, default_duration_);
|
| +
|
| if (!codec_id_.empty())
|
| size += StringElementSize(kWebMIdCodecID, codec_id_);
|
|
|
| @@ -193,6 +328,14 @@ int TracksBuilder::Track::GetPayloadSize() const {
|
| if (!language_.empty())
|
| size += StringElementSize(kWebMIdLanguage, language_);
|
|
|
| + if (GetVideoPayloadSize() > 0) {
|
| + size += MasterElementSize(kWebMIdVideo, GetVideoPayloadSize());
|
| + }
|
| +
|
| + if (GetAudioPayloadSize() > 0) {
|
| + size += MasterElementSize(kWebMIdAudio, GetAudioPayloadSize());
|
| + }
|
| +
|
| return size;
|
| }
|
|
|
| @@ -203,6 +346,9 @@ void TracksBuilder::Track::Write(uint8** buf, int* buf_size) const {
|
| WriteIntElement(buf, buf_size, kWebMIdTrackType, track_type_);
|
| WriteIntElement(buf, buf_size, kWebMIdTrackUID, track_uid_);
|
|
|
| + if (default_duration_ >= 0)
|
| + WriteIntElement(buf, buf_size, kWebMIdDefaultDuration, default_duration_);
|
| +
|
| if (!codec_id_.empty())
|
| WriteStringElement(buf, buf_size, kWebMIdCodecID, codec_id_);
|
|
|
| @@ -211,6 +357,28 @@ void TracksBuilder::Track::Write(uint8** buf, int* buf_size) const {
|
|
|
| if (!language_.empty())
|
| WriteStringElement(buf, buf_size, kWebMIdLanguage, language_);
|
| +
|
| + if (GetVideoPayloadSize() > 0) {
|
| + WriteMasterElement(buf, buf_size, kWebMIdVideo, GetVideoPayloadSize());
|
| +
|
| + if (video_pixel_width_ >= 0)
|
| + WriteIntElement(buf, buf_size, kWebMIdPixelWidth, video_pixel_width_);
|
| +
|
| + if (video_pixel_height_ >= 0)
|
| + WriteIntElement(buf, buf_size, kWebMIdPixelHeight, video_pixel_height_);
|
| + }
|
| +
|
| + if (GetAudioPayloadSize() > 0) {
|
| + WriteMasterElement(buf, buf_size, kWebMIdAudio, GetAudioPayloadSize());
|
| +
|
| + if (audio_channels_ >= 0)
|
| + WriteIntElement(buf, buf_size, kWebMIdChannels, audio_channels_);
|
| +
|
| + if (audio_sampling_frequency_ >= 0) {
|
| + WriteDoubleElement(buf, buf_size, kWebMIdSamplingFrequency,
|
| + audio_sampling_frequency_);
|
| + }
|
| + }
|
| }
|
|
|
| } // namespace media
|
|
|