Make webm parser compile and unittest pass
Change-Id: Ib93fbb3eba6f0638f3aa57a9a47e73e8738792d1
This commit is contained in:
parent
5a4234f4da
commit
845766f69a
|
@ -69,6 +69,8 @@
|
||||||
'stream_info.h',
|
'stream_info.h',
|
||||||
'text_track.h',
|
'text_track.h',
|
||||||
'timestamp.h',
|
'timestamp.h',
|
||||||
|
'text_track_config.cc',
|
||||||
|
'text_track_config.h',
|
||||||
'video_stream_info.cc',
|
'video_stream_info.cc',
|
||||||
'video_stream_info.h',
|
'video_stream_info.h',
|
||||||
'widevine_key_source.cc',
|
'widevine_key_source.cc',
|
||||||
|
|
|
@ -19,6 +19,7 @@ enum StreamType {
|
||||||
kStreamUnknown = 0,
|
kStreamUnknown = 0,
|
||||||
kStreamAudio,
|
kStreamAudio,
|
||||||
kStreamVideo,
|
kStreamVideo,
|
||||||
|
kStreamText,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Abstract class holds stream information.
|
/// Abstract class holds stream information.
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "packager/media/formats/webm/cluster_builder.h"
|
#include "packager/media/formats/webm/cluster_builder.h"
|
||||||
|
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/media/base/data_buffer.h"
|
|
||||||
#include "packager/media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
# Copyright 2015 Google Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# Use of this source code is governed by a BSD-style
|
||||||
|
# license that can be found in the LICENSE file or at
|
||||||
|
# https://developers.google.com/open-source/licenses/bsd
|
||||||
|
|
||||||
|
{
|
||||||
|
'includes': [
|
||||||
|
'../../../common.gypi',
|
||||||
|
],
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'webm',
|
||||||
|
'type': '<(component)',
|
||||||
|
'sources': [
|
||||||
|
'webm_audio_client.cc',
|
||||||
|
'webm_audio_client.h',
|
||||||
|
'webm_cluster_parser.cc',
|
||||||
|
'webm_cluster_parser.h',
|
||||||
|
'webm_constants.cc',
|
||||||
|
'webm_constants.h',
|
||||||
|
'webm_content_encodings.cc',
|
||||||
|
'webm_content_encodings.h',
|
||||||
|
'webm_content_encodings_client.cc',
|
||||||
|
'webm_content_encodings_client.h',
|
||||||
|
'webm_crypto_helpers.cc',
|
||||||
|
'webm_crypto_helpers.h',
|
||||||
|
'webm_info_parser.cc',
|
||||||
|
'webm_info_parser.h',
|
||||||
|
'webm_parser.cc',
|
||||||
|
'webm_parser.h',
|
||||||
|
'webm_stream_parser.cc',
|
||||||
|
'webm_stream_parser.h',
|
||||||
|
'webm_tracks_parser.cc',
|
||||||
|
'webm_tracks_parser.h',
|
||||||
|
'webm_video_client.cc',
|
||||||
|
'webm_video_client.h',
|
||||||
|
'webm_webvtt_parser.cc',
|
||||||
|
'webm_webvtt_parser.h'
|
||||||
|
],
|
||||||
|
'dependencies': [
|
||||||
|
'../../base/media_base.gyp:base',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'target_name': 'webm_unittest',
|
||||||
|
'type': '<(gtest_target_type)',
|
||||||
|
'sources': [
|
||||||
|
'cluster_builder.cc',
|
||||||
|
'cluster_builder.h',
|
||||||
|
'opus_packet_builder.cc',
|
||||||
|
'opus_packet_builder.h',
|
||||||
|
'tracks_builder.cc',
|
||||||
|
'tracks_builder.h',
|
||||||
|
'webm_cluster_parser_unittest.cc',
|
||||||
|
'webm_content_encodings_client_unittest.cc',
|
||||||
|
'webm_parser_unittest.cc',
|
||||||
|
'webm_tracks_parser_unittest.cc',
|
||||||
|
'webm_webvtt_parser_unittest.cc',
|
||||||
|
],
|
||||||
|
'dependencies': [
|
||||||
|
'../../../testing/gtest.gyp:gtest',
|
||||||
|
'../../../testing/gmock.gyp:gmock',
|
||||||
|
'../../test/media_test.gyp:media_test_support',
|
||||||
|
'webm',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
|
@ -4,10 +4,14 @@
|
||||||
|
|
||||||
#include "packager/media/formats/webm/webm_audio_client.h"
|
#include "packager/media/formats/webm/webm_audio_client.h"
|
||||||
|
|
||||||
#include "packager/media/base/audio_decoder_config.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/media/base/channel_layout.h"
|
|
||||||
#include "packager/media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// Timestamps are represented in double in WebM. Convert to uint64_t in us.
|
||||||
|
const uint32_t kWebMTimeScale = 1000000u;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
|
@ -24,16 +28,12 @@ void WebMAudioClient::Reset() {
|
||||||
output_samples_per_second_ = -1;
|
output_samples_per_second_ = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMAudioClient::InitializeConfig(
|
scoped_refptr<AudioStreamInfo> WebMAudioClient::GetAudioStreamInfo(
|
||||||
|
int64_t track_num,
|
||||||
const std::string& codec_id,
|
const std::string& codec_id,
|
||||||
const std::vector<uint8_t>& codec_private,
|
const std::vector<uint8_t>& codec_private,
|
||||||
int64_t seek_preroll,
|
const std::string& language,
|
||||||
int64_t codec_delay,
|
bool is_encrypted) {
|
||||||
bool is_encrypted,
|
|
||||||
AudioDecoderConfig* config) {
|
|
||||||
DCHECK(config);
|
|
||||||
SampleFormat sample_format = kSampleFormatPlanarF32;
|
|
||||||
|
|
||||||
AudioCodec audio_codec = kUnknownAudioCodec;
|
AudioCodec audio_codec = kUnknownAudioCodec;
|
||||||
if (codec_id == "A_VORBIS") {
|
if (codec_id == "A_VORBIS") {
|
||||||
audio_codec = kCodecVorbis;
|
audio_codec = kCodecVorbis;
|
||||||
|
@ -41,32 +41,21 @@ bool WebMAudioClient::InitializeConfig(
|
||||||
audio_codec = kCodecOpus;
|
audio_codec = kCodecOpus;
|
||||||
} else {
|
} else {
|
||||||
LOG(ERROR) << "Unsupported audio codec_id " << codec_id;
|
LOG(ERROR) << "Unsupported audio codec_id " << codec_id;
|
||||||
return false;
|
return scoped_refptr<AudioStreamInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (samples_per_second_ <= 0)
|
if (samples_per_second_ <= 0)
|
||||||
return false;
|
return scoped_refptr<AudioStreamInfo>();
|
||||||
|
|
||||||
// Set channel layout default if a Channels element was not present.
|
// Set channel layout default if a Channels element was not present.
|
||||||
if (channels_ == -1)
|
if (channels_ == -1)
|
||||||
channels_ = 1;
|
channels_ = 1;
|
||||||
|
|
||||||
ChannelLayout channel_layout = GuessChannelLayout(channels_);
|
uint32_t sampling_frequency = samples_per_second_;
|
||||||
|
|
||||||
if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) {
|
|
||||||
LOG(ERROR) << "Unsupported channel count " << channels_;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int samples_per_second = samples_per_second_;
|
|
||||||
if (output_samples_per_second_ > 0)
|
|
||||||
samples_per_second = output_samples_per_second_;
|
|
||||||
|
|
||||||
// Always use 48kHz for OPUS. See the "Input Sample Rate" section of the
|
// Always use 48kHz for OPUS. See the "Input Sample Rate" section of the
|
||||||
// spec: http://tools.ietf.org/html/draft-terriberry-oggopus-01#page-11
|
// spec: http://tools.ietf.org/html/draft-terriberry-oggopus-01#page-11
|
||||||
if (audio_codec == kCodecOpus) {
|
if (audio_codec == kCodecOpus) {
|
||||||
samples_per_second = 48000;
|
sampling_frequency = 48000;
|
||||||
sample_format = kSampleFormatF32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t* extra_data = NULL;
|
const uint8_t* extra_data = NULL;
|
||||||
|
@ -76,27 +65,12 @@ bool WebMAudioClient::InitializeConfig(
|
||||||
extra_data_size = codec_private.size();
|
extra_data_size = codec_private.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert |codec_delay| from nanoseconds into frames.
|
const uint32_t kSampleSizeInBits = 4u;
|
||||||
int codec_delay_in_frames = 0;
|
return scoped_refptr<AudioStreamInfo>(new AudioStreamInfo(
|
||||||
if (codec_delay != -1) {
|
track_num, kWebMTimeScale, 0, audio_codec,
|
||||||
codec_delay_in_frames =
|
AudioStreamInfo::GetCodecString(audio_codec, 0), language,
|
||||||
0.5 +
|
kSampleSizeInBits, channels_, sampling_frequency, extra_data,
|
||||||
samples_per_second * (static_cast<double>(codec_delay) /
|
extra_data_size, is_encrypted));
|
||||||
base::Time::kNanosecondsPerSecond);
|
|
||||||
}
|
|
||||||
|
|
||||||
config->Initialize(
|
|
||||||
audio_codec,
|
|
||||||
sample_format,
|
|
||||||
channel_layout,
|
|
||||||
samples_per_second,
|
|
||||||
extra_data,
|
|
||||||
extra_data_size,
|
|
||||||
is_encrypted,
|
|
||||||
base::TimeDelta::FromMicroseconds(
|
|
||||||
(seek_preroll != -1 ? seek_preroll : 0) / 1000),
|
|
||||||
codec_delay_in_frames);
|
|
||||||
return config->IsValidConfig();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMAudioClient::OnUInt(int id, int64_t val) {
|
bool WebMAudioClient::OnUInt(int id, int64_t val) {
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
|
#include "packager/media/base/audio_stream_info.h"
|
||||||
#include "packager/media/formats/webm/webm_parser.h"
|
#include "packager/media/formats/webm/webm_parser.h"
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
|
@ -23,18 +25,18 @@ class WebMAudioClient : public WebMParserClient {
|
||||||
// Reset this object's state so it can process a new audio track element.
|
// Reset this object's state so it can process a new audio track element.
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
// Initialize |config| with the data in |codec_id|, |codec_private|,
|
// Create an AudioStreamInfo with the data in |track_num|, |codec_id|,
|
||||||
// |is_encrypted| and the fields parsed from the last audio track element this
|
// |codec_private|, |is_encrypted| and the fields parsed from the last audio
|
||||||
// object was used to parse.
|
// track element this object was used to parse.
|
||||||
// Returns true if |config| was successfully initialized.
|
// Returns an AudioStreamInfo scoped_refptr if successful.
|
||||||
// Returns false if there was unexpected values in the provided parameters or
|
// Returns an empty scoped_refptr if there was unexpected values in the
|
||||||
// audio track element fields.
|
// provided parameters or audio track element fields.
|
||||||
bool InitializeConfig(const std::string& codec_id,
|
scoped_refptr<AudioStreamInfo> GetAudioStreamInfo(
|
||||||
const std::vector<uint8_t>& codec_private,
|
int64_t track_num,
|
||||||
const int64_t seek_preroll,
|
const std::string& codec_id,
|
||||||
const int64_t codec_delay,
|
const std::vector<uint8_t>& codec_private,
|
||||||
bool is_encrypted,
|
const std::string& language,
|
||||||
AudioDecoderConfig* config);
|
bool is_encrypted);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// WebMParserClient implementation.
|
// WebMParserClient implementation.
|
||||||
|
|
|
@ -54,9 +54,9 @@ bool WebMCreateDecryptConfig(const uint8_t* data,
|
||||||
}
|
}
|
||||||
|
|
||||||
decrypt_config->reset(new DecryptConfig(
|
decrypt_config->reset(new DecryptConfig(
|
||||||
std::string(reinterpret_cast<const char*>(key_id), key_id_size),
|
std::vector<uint8_t>(key_id, key_id + key_id_size),
|
||||||
counter_block,
|
std::vector<uint8_t>(counter_block.begin(), counter_block.end()),
|
||||||
std::vector<SubsampleEntry>()));
|
frame_offset, std::vector<SubsampleEntry>()));
|
||||||
*data_offset = frame_offset;
|
*data_offset = frame_offset;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include "packager/base/macros.h"
|
#include "packager/base/macros.h"
|
||||||
#include "packager/base/memory/scoped_ptr.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
#include "packager/media/base/decoder_buffer.h"
|
#include "packager/media/base/decrypt_config.h"
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "packager/base/callback.h"
|
#include "packager/base/callback.h"
|
||||||
#include "packager/base/callback_helpers.h"
|
#include "packager/base/callback_helpers.h"
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/media/base/timestamp_constants.h"
|
#include "packager/media/base/timestamp.h"
|
||||||
#include "packager/media/formats/webm/webm_cluster_parser.h"
|
#include "packager/media/formats/webm/webm_cluster_parser.h"
|
||||||
#include "packager/media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
#include "packager/media/formats/webm/webm_content_encodings.h"
|
#include "packager/media/formats/webm/webm_content_encodings.h"
|
||||||
|
@ -29,29 +29,18 @@ WebMStreamParser::~WebMStreamParser() {
|
||||||
|
|
||||||
void WebMStreamParser::Init(
|
void WebMStreamParser::Init(
|
||||||
const InitCB& init_cb,
|
const InitCB& init_cb,
|
||||||
const NewConfigCB& config_cb,
|
const NewSampleCB& new_sample_cb,
|
||||||
const NewBuffersCB& new_buffers_cb,
|
KeySource* decryption_key_source) {
|
||||||
bool ignore_text_tracks,
|
|
||||||
const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
|
|
||||||
const NewMediaSegmentCB& new_segment_cb,
|
|
||||||
const base::Closure& end_of_segment_cb) {
|
|
||||||
DCHECK_EQ(state_, kWaitingForInit);
|
DCHECK_EQ(state_, kWaitingForInit);
|
||||||
DCHECK(init_cb_.is_null());
|
DCHECK(init_cb_.is_null());
|
||||||
DCHECK(!init_cb.is_null());
|
DCHECK(!init_cb.is_null());
|
||||||
DCHECK(!config_cb.is_null());
|
DCHECK(!new_sample_cb.is_null());
|
||||||
DCHECK(!new_buffers_cb.is_null());
|
|
||||||
DCHECK(!encrypted_media_init_data_cb.is_null());
|
|
||||||
DCHECK(!new_segment_cb.is_null());
|
|
||||||
DCHECK(!end_of_segment_cb.is_null());
|
|
||||||
|
|
||||||
ChangeState(kParsingHeaders);
|
ChangeState(kParsingHeaders);
|
||||||
init_cb_ = init_cb;
|
init_cb_ = init_cb;
|
||||||
config_cb_ = config_cb;
|
new_sample_cb_ = new_sample_cb;
|
||||||
new_buffers_cb_ = new_buffers_cb;
|
decryption_key_source_ = decryption_key_source;
|
||||||
ignore_text_tracks_ = ignore_text_tracks;
|
ignore_text_tracks_ = true;
|
||||||
encrypted_media_init_data_cb_ = encrypted_media_init_data_cb;
|
|
||||||
new_segment_cb_ = new_segment_cb;
|
|
||||||
end_of_segment_cb_ = end_of_segment_cb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebMStreamParser::Flush() {
|
void WebMStreamParser::Flush() {
|
||||||
|
@ -62,7 +51,6 @@ void WebMStreamParser::Flush() {
|
||||||
cluster_parser_->Reset();
|
cluster_parser_->Reset();
|
||||||
if (state_ == kParsingClusters) {
|
if (state_ == kParsingClusters) {
|
||||||
ChangeState(kParsingHeaders);
|
ChangeState(kParsingHeaders);
|
||||||
end_of_segment_cb_.Run();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +146,6 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8_t* data, int size) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ChangeState(kParsingClusters);
|
ChangeState(kParsingClusters);
|
||||||
new_segment_cb_.Run();
|
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
case kWebMIdSegment:
|
case kWebMIdSegment:
|
||||||
|
@ -196,38 +183,22 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8_t* data, int size) {
|
||||||
bytes_parsed += result;
|
bytes_parsed += result;
|
||||||
|
|
||||||
double timecode_scale_in_us = info_parser.timecode_scale() / 1000.0;
|
double timecode_scale_in_us = info_parser.timecode_scale() / 1000.0;
|
||||||
InitParameters params(kInfiniteDuration());
|
int64_t duration_in_us = info_parser.duration() * timecode_scale_in_us;
|
||||||
|
|
||||||
if (info_parser.duration() > 0) {
|
std::vector<scoped_refptr<StreamInfo>> streams;
|
||||||
int64_t duration_in_us = info_parser.duration() * timecode_scale_in_us;
|
scoped_refptr<AudioStreamInfo> audio_stream_info =
|
||||||
params.duration = base::TimeDelta::FromMicroseconds(duration_in_us);
|
tracks_parser.audio_stream_info();
|
||||||
}
|
streams.push_back(tracks_parser.audio_stream_info());
|
||||||
|
streams.back()->set_duration(duration_in_us);
|
||||||
params.timeline_offset = info_parser.date_utc();
|
if (streams.back()->is_encrypted())
|
||||||
|
|
||||||
if (unknown_segment_size_ && (info_parser.duration() <= 0) &&
|
|
||||||
!info_parser.date_utc().is_null()) {
|
|
||||||
params.liveness = DemuxerStream::LIVENESS_LIVE;
|
|
||||||
} else if (info_parser.duration() >= 0) {
|
|
||||||
params.liveness = DemuxerStream::LIVENESS_RECORDED;
|
|
||||||
} else {
|
|
||||||
params.liveness = DemuxerStream::LIVENESS_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AudioDecoderConfig& audio_config = tracks_parser.audio_decoder_config();
|
|
||||||
if (audio_config.is_encrypted())
|
|
||||||
OnEncryptedMediaInitData(tracks_parser.audio_encryption_key_id());
|
OnEncryptedMediaInitData(tracks_parser.audio_encryption_key_id());
|
||||||
|
|
||||||
const VideoDecoderConfig& video_config = tracks_parser.video_decoder_config();
|
streams.push_back(tracks_parser.video_stream_info());
|
||||||
if (video_config.is_encrypted())
|
streams.back()->set_duration(duration_in_us);
|
||||||
|
if (streams.back()->is_encrypted())
|
||||||
OnEncryptedMediaInitData(tracks_parser.video_encryption_key_id());
|
OnEncryptedMediaInitData(tracks_parser.video_encryption_key_id());
|
||||||
|
|
||||||
if (!config_cb_.Run(audio_config,
|
init_cb_.Run(streams);
|
||||||
video_config,
|
|
||||||
tracks_parser.text_tracks())) {
|
|
||||||
DVLOG(1) << "New config data isn't allowed.";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cluster_parser_.reset(new WebMClusterParser(
|
cluster_parser_.reset(new WebMClusterParser(
|
||||||
info_parser.timecode_scale(), tracks_parser.audio_track_num(),
|
info_parser.timecode_scale(), tracks_parser.audio_track_num(),
|
||||||
|
@ -236,10 +207,8 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8_t* data, int size) {
|
||||||
tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us),
|
tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us),
|
||||||
tracks_parser.text_tracks(), tracks_parser.ignored_tracks(),
|
tracks_parser.text_tracks(), tracks_parser.ignored_tracks(),
|
||||||
tracks_parser.audio_encryption_key_id(),
|
tracks_parser.audio_encryption_key_id(),
|
||||||
tracks_parser.video_encryption_key_id(), audio_config.codec());
|
tracks_parser.video_encryption_key_id(), audio_stream_info->codec(),
|
||||||
|
new_sample_cb_));
|
||||||
if (!init_cb_.is_null())
|
|
||||||
base::ResetAndReturn(&init_cb_).Run(params);
|
|
||||||
|
|
||||||
return bytes_parsed;
|
return bytes_parsed;
|
||||||
}
|
}
|
||||||
|
@ -252,29 +221,16 @@ int WebMStreamParser::ParseCluster(const uint8_t* data, int size) {
|
||||||
if (bytes_parsed < 0)
|
if (bytes_parsed < 0)
|
||||||
return bytes_parsed;
|
return bytes_parsed;
|
||||||
|
|
||||||
const BufferQueue& audio_buffers = cluster_parser_->GetAudioBuffers();
|
|
||||||
const BufferQueue& video_buffers = cluster_parser_->GetVideoBuffers();
|
|
||||||
const TextBufferQueueMap& text_map = cluster_parser_->GetTextBuffers();
|
|
||||||
|
|
||||||
bool cluster_ended = cluster_parser_->cluster_ended();
|
bool cluster_ended = cluster_parser_->cluster_ended();
|
||||||
|
|
||||||
if ((!audio_buffers.empty() || !video_buffers.empty() ||
|
|
||||||
!text_map.empty()) &&
|
|
||||||
!new_buffers_cb_.Run(audio_buffers, video_buffers, text_map)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cluster_ended) {
|
if (cluster_ended) {
|
||||||
ChangeState(kParsingHeaders);
|
ChangeState(kParsingHeaders);
|
||||||
end_of_segment_cb_.Run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytes_parsed;
|
return bytes_parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebMStreamParser::OnEncryptedMediaInitData(const std::string& key_id) {
|
void WebMStreamParser::OnEncryptedMediaInitData(const std::string& key_id) {
|
||||||
std::vector<uint8_t> key_id_vector(key_id.begin(), key_id.end());
|
NOTIMPLEMENTED() << "WebM decryption is not implemented yet.";
|
||||||
encrypted_media_init_data_cb_.Run(EmeInitDataType::WEBM, key_id_vector);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
|
|
@ -7,29 +7,23 @@
|
||||||
|
|
||||||
#include "packager/base/callback_forward.h"
|
#include "packager/base/callback_forward.h"
|
||||||
#include "packager/base/memory/ref_counted.h"
|
#include "packager/base/memory/ref_counted.h"
|
||||||
#include "packager/media/base/audio_decoder_config.h"
|
|
||||||
#include "packager/media/base/byte_queue.h"
|
#include "packager/media/base/byte_queue.h"
|
||||||
#include "packager/media/base/stream_parser.h"
|
#include "packager/media/base/media_parser.h"
|
||||||
#include "packager/media/base/video_decoder_config.h"
|
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
class WebMClusterParser;
|
class WebMClusterParser;
|
||||||
|
|
||||||
class WebMStreamParser : public StreamParser {
|
class WebMStreamParser : public MediaParser {
|
||||||
public:
|
public:
|
||||||
WebMStreamParser();
|
WebMStreamParser();
|
||||||
~WebMStreamParser() override;
|
~WebMStreamParser() override;
|
||||||
|
|
||||||
// StreamParser implementation.
|
// StreamParser implementation.
|
||||||
void Init(const InitCB& init_cb,
|
void Init(const InitCB& init_cb,
|
||||||
const NewConfigCB& config_cb,
|
const NewSampleCB& new_sample_cb,
|
||||||
const NewBuffersCB& new_buffers_cb,
|
KeySource* decryption_key_source) override;
|
||||||
bool ignore_text_tracks,
|
|
||||||
const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
|
|
||||||
const NewMediaSegmentCB& new_segment_cb,
|
|
||||||
const base::Closure& end_of_segment_cb) override;
|
|
||||||
void Flush() override;
|
void Flush() override;
|
||||||
bool Parse(const uint8_t* buf, int size) override;
|
bool Parse(const uint8_t* buf, int size) override;
|
||||||
|
|
||||||
|
@ -67,13 +61,9 @@ class WebMStreamParser : public StreamParser {
|
||||||
|
|
||||||
State state_;
|
State state_;
|
||||||
InitCB init_cb_;
|
InitCB init_cb_;
|
||||||
NewConfigCB config_cb_;
|
NewSampleCB new_sample_cb_;
|
||||||
NewBuffersCB new_buffers_cb_;
|
KeySource* decryption_key_source_;
|
||||||
bool ignore_text_tracks_;
|
bool ignore_text_tracks_;
|
||||||
EncryptedMediaInitDataCB encrypted_media_init_data_cb_;
|
|
||||||
|
|
||||||
NewMediaSegmentCB new_segment_cb_;
|
|
||||||
base::Closure end_of_segment_cb_;
|
|
||||||
|
|
||||||
bool unknown_segment_size_;
|
bool unknown_segment_size_;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/base/strings/string_number_conversions.h"
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
#include "packager/base/strings/string_util.h"
|
#include "packager/base/strings/string_util.h"
|
||||||
#include "packager/media/base/timestamp_constants.h"
|
#include "packager/media/base/timestamp.h"
|
||||||
#include "packager/media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
#include "packager/media/formats/webm/webm_content_encodings.h"
|
#include "packager/media/formats/webm/webm_content_encodings.h"
|
||||||
|
|
||||||
|
@ -30,19 +30,19 @@ static TextKind CodecIdToTextKind(const std::string& codec_id) {
|
||||||
return kTextNone;
|
return kTextNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
static base::TimeDelta PrecisionCappedDefaultDuration(
|
static int64_t PrecisionCappedDefaultDuration(
|
||||||
const double timecode_scale_in_us,
|
const double timecode_scale_in_us,
|
||||||
const int64_t duration_in_ns) {
|
const int64_t duration_in_ns) {
|
||||||
if (duration_in_ns <= 0)
|
if (duration_in_ns <= 0)
|
||||||
return kNoTimestamp();
|
return kNoTimestamp;
|
||||||
|
|
||||||
int64_t mult = duration_in_ns / 1000;
|
int64_t mult = duration_in_ns / 1000;
|
||||||
mult /= timecode_scale_in_us;
|
mult /= timecode_scale_in_us;
|
||||||
if (mult == 0)
|
if (mult == 0)
|
||||||
return kNoTimestamp();
|
return kNoTimestamp;
|
||||||
|
|
||||||
mult = static_cast<double>(mult) * timecode_scale_in_us;
|
mult = static_cast<double>(mult) * timecode_scale_in_us;
|
||||||
return base::TimeDelta::FromMicroseconds(mult);
|
return mult;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebMTracksParser::WebMTracksParser(bool ignore_text_tracks)
|
WebMTracksParser::WebMTracksParser(bool ignore_text_tracks)
|
||||||
|
@ -70,10 +70,10 @@ int WebMTracksParser::Parse(const uint8_t* buf, int size) {
|
||||||
track_language_.clear();
|
track_language_.clear();
|
||||||
audio_track_num_ = -1;
|
audio_track_num_ = -1;
|
||||||
audio_default_duration_ = -1;
|
audio_default_duration_ = -1;
|
||||||
audio_decoder_config_ = AudioDecoderConfig();
|
audio_stream_info_ = nullptr;
|
||||||
video_track_num_ = -1;
|
video_track_num_ = -1;
|
||||||
video_default_duration_ = -1;
|
video_default_duration_ = -1;
|
||||||
video_decoder_config_ = VideoDecoderConfig();
|
video_stream_info_ = nullptr;
|
||||||
text_tracks_.clear();
|
text_tracks_.clear();
|
||||||
ignored_tracks_.clear();
|
ignored_tracks_.clear();
|
||||||
|
|
||||||
|
@ -87,13 +87,13 @@ int WebMTracksParser::Parse(const uint8_t* buf, int size) {
|
||||||
return parser.IsParsingComplete() ? result : 0;
|
return parser.IsParsingComplete() ? result : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
base::TimeDelta WebMTracksParser::GetAudioDefaultDuration(
|
int64_t WebMTracksParser::GetAudioDefaultDuration(
|
||||||
const double timecode_scale_in_us) const {
|
const double timecode_scale_in_us) const {
|
||||||
return PrecisionCappedDefaultDuration(timecode_scale_in_us,
|
return PrecisionCappedDefaultDuration(timecode_scale_in_us,
|
||||||
audio_default_duration_);
|
audio_default_duration_);
|
||||||
}
|
}
|
||||||
|
|
||||||
base::TimeDelta WebMTracksParser::GetVideoDefaultDuration(
|
int64_t WebMTracksParser::GetVideoDefaultDuration(
|
||||||
const double timecode_scale_in_us) const {
|
const double timecode_scale_in_us) const {
|
||||||
return PrecisionCappedDefaultDuration(timecode_scale_in_us,
|
return PrecisionCappedDefaultDuration(timecode_scale_in_us,
|
||||||
video_default_duration_);
|
video_default_duration_);
|
||||||
|
@ -201,12 +201,12 @@ bool WebMTracksParser::OnListEnd(int id) {
|
||||||
}
|
}
|
||||||
audio_default_duration_ = default_duration_;
|
audio_default_duration_ = default_duration_;
|
||||||
|
|
||||||
DCHECK(!audio_decoder_config_.IsValidConfig());
|
DCHECK(!audio_stream_info_);
|
||||||
if (!audio_client_.InitializeConfig(
|
audio_stream_info_ = audio_client_.GetAudioStreamInfo(
|
||||||
codec_id_, codec_private_, seek_preroll_, codec_delay_,
|
audio_track_num_, codec_id_, codec_private_, track_language_,
|
||||||
!audio_encryption_key_id_.empty(), &audio_decoder_config_)) {
|
!audio_encryption_key_id_.empty());
|
||||||
|
if (!audio_stream_info_)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
DLOG(INFO) << "Ignoring audio track " << track_num_;
|
DLOG(INFO) << "Ignoring audio track " << track_num_;
|
||||||
ignored_tracks_.insert(track_num_);
|
ignored_tracks_.insert(track_num_);
|
||||||
|
@ -223,12 +223,12 @@ bool WebMTracksParser::OnListEnd(int id) {
|
||||||
}
|
}
|
||||||
video_default_duration_ = default_duration_;
|
video_default_duration_ = default_duration_;
|
||||||
|
|
||||||
DCHECK(!video_decoder_config_.IsValidConfig());
|
DCHECK(!video_stream_info_);
|
||||||
if (!video_client_.InitializeConfig(
|
video_stream_info_ = video_client_.GetVideoStreamInfo(
|
||||||
codec_id_, codec_private_, !video_encryption_key_id_.empty(),
|
video_track_num_, codec_id_, codec_private_,
|
||||||
&video_decoder_config_)) {
|
!video_encryption_key_id_.empty());
|
||||||
|
if (!video_stream_info_)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
DLOG(INFO) << "Ignoring video track " << track_num_;
|
DLOG(INFO) << "Ignoring video track " << track_num_;
|
||||||
ignored_tracks_.insert(track_num_);
|
ignored_tracks_.insert(track_num_);
|
||||||
|
|
|
@ -13,9 +13,9 @@
|
||||||
#include "packager/base/compiler_specific.h"
|
#include "packager/base/compiler_specific.h"
|
||||||
#include "packager/base/memory/scoped_ptr.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
#include "packager/base/time/time.h"
|
#include "packager/base/time/time.h"
|
||||||
#include "packager/media/base/audio_decoder_config.h"
|
#include "packager/media/base/audio_stream_info.h"
|
||||||
#include "packager/media/base/text_track_config.h"
|
#include "packager/media/base/text_track_config.h"
|
||||||
#include "packager/media/base/video_decoder_config.h"
|
#include "packager/media/base/video_stream_info.h"
|
||||||
#include "packager/media/formats/webm/webm_audio_client.h"
|
#include "packager/media/formats/webm/webm_audio_client.h"
|
||||||
#include "packager/media/formats/webm/webm_content_encodings_client.h"
|
#include "packager/media/formats/webm/webm_content_encodings_client.h"
|
||||||
#include "packager/media/formats/webm/webm_parser.h"
|
#include "packager/media/formats/webm/webm_parser.h"
|
||||||
|
@ -44,10 +44,8 @@ class WebMTracksParser : public WebMParserClient {
|
||||||
// video track, returns that value converted from ns to base::TimeDelta with
|
// video track, returns that value converted from ns to base::TimeDelta with
|
||||||
// precision not greater than |timecode_scale_in_us|. Defaults to
|
// precision not greater than |timecode_scale_in_us|. Defaults to
|
||||||
// kNoTimestamp().
|
// kNoTimestamp().
|
||||||
base::TimeDelta GetAudioDefaultDuration(
|
int64_t GetAudioDefaultDuration(const double timecode_scale_in_us) const;
|
||||||
const double timecode_scale_in_us) const;
|
int64_t GetVideoDefaultDuration(const double timecode_scale_in_us) const;
|
||||||
base::TimeDelta GetVideoDefaultDuration(
|
|
||||||
const double timecode_scale_in_us) const;
|
|
||||||
|
|
||||||
const std::set<int64_t>& ignored_tracks() const { return ignored_tracks_; }
|
const std::set<int64_t>& ignored_tracks() const { return ignored_tracks_; }
|
||||||
|
|
||||||
|
@ -55,16 +53,16 @@ class WebMTracksParser : public WebMParserClient {
|
||||||
return audio_encryption_key_id_;
|
return audio_encryption_key_id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AudioDecoderConfig& audio_decoder_config() {
|
scoped_refptr<AudioStreamInfo> audio_stream_info() {
|
||||||
return audio_decoder_config_;
|
return audio_stream_info_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& video_encryption_key_id() const {
|
const std::string& video_encryption_key_id() const {
|
||||||
return video_encryption_key_id_;
|
return video_encryption_key_id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VideoDecoderConfig& video_decoder_config() {
|
scoped_refptr<VideoStreamInfo> video_stream_info() {
|
||||||
return video_decoder_config_;
|
return video_stream_info_;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::map<int, TextTrackConfig> TextTracks;
|
typedef std::map<int, TextTrackConfig> TextTracks;
|
||||||
|
@ -104,10 +102,10 @@ class WebMTracksParser : public WebMParserClient {
|
||||||
std::string video_encryption_key_id_;
|
std::string video_encryption_key_id_;
|
||||||
|
|
||||||
WebMAudioClient audio_client_;
|
WebMAudioClient audio_client_;
|
||||||
AudioDecoderConfig audio_decoder_config_;
|
scoped_refptr<AudioStreamInfo> audio_stream_info_;
|
||||||
|
|
||||||
WebMVideoClient video_client_;
|
WebMVideoClient video_client_;
|
||||||
VideoDecoderConfig video_decoder_config_;
|
scoped_refptr<VideoStreamInfo> video_stream_info_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(WebMTracksParser);
|
DISALLOW_COPY_AND_ASSIGN(WebMTracksParser);
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/media/base/channel_layout.h"
|
#include "packager/media/base/timestamp.h"
|
||||||
#include "packager/media/base/timestamp_constants.h"
|
|
||||||
#include "packager/media/formats/webm/tracks_builder.h"
|
#include "packager/media/formats/webm/tracks_builder.h"
|
||||||
#include "packager/media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
|
@ -140,20 +139,22 @@ TEST_F(WebMTracksParserTest, AudioVideoDefaultDurationUnset) {
|
||||||
EXPECT_LE(0, result);
|
EXPECT_LE(0, result);
|
||||||
EXPECT_EQ(static_cast<int>(buf.size()), result);
|
EXPECT_EQ(static_cast<int>(buf.size()), result);
|
||||||
|
|
||||||
EXPECT_EQ(kNoTimestamp(),
|
EXPECT_EQ(kNoTimestamp,
|
||||||
parser->GetAudioDefaultDuration(kDefaultTimecodeScaleInUs));
|
parser->GetAudioDefaultDuration(kDefaultTimecodeScaleInUs));
|
||||||
EXPECT_EQ(kNoTimestamp(),
|
EXPECT_EQ(kNoTimestamp,
|
||||||
parser->GetVideoDefaultDuration(kDefaultTimecodeScaleInUs));
|
parser->GetVideoDefaultDuration(kDefaultTimecodeScaleInUs));
|
||||||
|
|
||||||
const VideoDecoderConfig& video_config = parser->video_decoder_config();
|
scoped_refptr<VideoStreamInfo> video_stream_info =
|
||||||
EXPECT_TRUE(video_config.IsValidConfig());
|
parser->video_stream_info();
|
||||||
EXPECT_EQ(320, video_config.coded_size().width());
|
EXPECT_TRUE(video_stream_info);
|
||||||
EXPECT_EQ(240, video_config.coded_size().height());
|
EXPECT_EQ(320u, video_stream_info->width());
|
||||||
|
EXPECT_EQ(240u, video_stream_info->height());
|
||||||
|
|
||||||
const AudioDecoderConfig& audio_config = parser->audio_decoder_config();
|
scoped_refptr<AudioStreamInfo> audio_stream_info =
|
||||||
EXPECT_TRUE(audio_config.IsValidConfig());
|
parser->audio_stream_info();
|
||||||
EXPECT_EQ(CHANNEL_LAYOUT_STEREO, audio_config.channel_layout());
|
EXPECT_TRUE(audio_stream_info);
|
||||||
EXPECT_EQ(8000, audio_config.samples_per_second());
|
EXPECT_EQ(2u, audio_stream_info->num_channels());
|
||||||
|
EXPECT_EQ(8000u, audio_stream_info->sampling_frequency());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebMTracksParserTest, AudioVideoDefaultDurationSet) {
|
TEST_F(WebMTracksParserTest, AudioVideoDefaultDurationSet) {
|
||||||
|
@ -169,14 +170,12 @@ TEST_F(WebMTracksParserTest, AudioVideoDefaultDurationSet) {
|
||||||
EXPECT_LE(0, result);
|
EXPECT_LE(0, result);
|
||||||
EXPECT_EQ(static_cast<int>(buf.size()), result);
|
EXPECT_EQ(static_cast<int>(buf.size()), result);
|
||||||
|
|
||||||
EXPECT_EQ(base::TimeDelta::FromMicroseconds(12000),
|
EXPECT_EQ(12000, parser->GetAudioDefaultDuration(kDefaultTimecodeScaleInUs));
|
||||||
parser->GetAudioDefaultDuration(kDefaultTimecodeScaleInUs));
|
EXPECT_EQ(985000,
|
||||||
EXPECT_EQ(base::TimeDelta::FromMicroseconds(985000),
|
|
||||||
parser->GetVideoDefaultDuration(5000.0)); // 5 ms resolution
|
parser->GetVideoDefaultDuration(5000.0)); // 5 ms resolution
|
||||||
EXPECT_EQ(kNoTimestamp(), parser->GetAudioDefaultDuration(12346.0));
|
EXPECT_EQ(kNoTimestamp, parser->GetAudioDefaultDuration(12346.0));
|
||||||
EXPECT_EQ(base::TimeDelta::FromMicroseconds(12345),
|
EXPECT_EQ(12345, parser->GetAudioDefaultDuration(12345.0));
|
||||||
parser->GetAudioDefaultDuration(12345.0));
|
EXPECT_EQ(12003,
|
||||||
EXPECT_EQ(base::TimeDelta::FromMicroseconds(12003),
|
|
||||||
parser->GetAudioDefaultDuration(1000.3)); // 1.0003 ms resolution
|
parser->GetAudioDefaultDuration(1000.3)); // 1.0003 ms resolution
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,25 @@
|
||||||
|
|
||||||
#include "packager/media/formats/webm/webm_video_client.h"
|
#include "packager/media/formats/webm/webm_video_client.h"
|
||||||
|
|
||||||
#include "packager/media/base/video_decoder_config.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Timestamps are represented in double in WebM. Convert to uint64_t in us.
|
||||||
|
const uint32_t kWebMTimeScale = 1000000u;
|
||||||
|
|
||||||
|
int64_t GetGreatestCommonDivisor(int64_t a, int64_t b) {
|
||||||
|
while (b) {
|
||||||
|
int64_t temp = b;
|
||||||
|
b = a % b;
|
||||||
|
a = temp;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
|
@ -30,31 +46,23 @@ void WebMVideoClient::Reset() {
|
||||||
alpha_mode_ = -1;
|
alpha_mode_ = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMVideoClient::InitializeConfig(
|
scoped_refptr<VideoStreamInfo> WebMVideoClient::GetVideoStreamInfo(
|
||||||
|
int64_t track_num,
|
||||||
const std::string& codec_id,
|
const std::string& codec_id,
|
||||||
const std::vector<uint8_t>& codec_private,
|
const std::vector<uint8_t>& codec_private,
|
||||||
bool is_encrypted,
|
bool is_encrypted) {
|
||||||
VideoDecoderConfig* config) {
|
|
||||||
DCHECK(config);
|
|
||||||
|
|
||||||
VideoCodec video_codec = kUnknownVideoCodec;
|
VideoCodec video_codec = kUnknownVideoCodec;
|
||||||
VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
|
|
||||||
if (codec_id == "V_VP8") {
|
if (codec_id == "V_VP8") {
|
||||||
video_codec = kCodecVP8;
|
video_codec = kCodecVP8;
|
||||||
profile = VP8PROFILE_ANY;
|
|
||||||
} else if (codec_id == "V_VP9") {
|
} else if (codec_id == "V_VP9") {
|
||||||
video_codec = kCodecVP9;
|
video_codec = kCodecVP9;
|
||||||
profile = VP9PROFILE_ANY;
|
|
||||||
} else {
|
} else {
|
||||||
LOG(ERROR) << "Unsupported video codec_id " << codec_id;
|
LOG(ERROR) << "Unsupported video codec_id " << codec_id;
|
||||||
return false;
|
return scoped_refptr<VideoStreamInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoPixelFormat format =
|
|
||||||
(alpha_mode_ == 1) ? PIXEL_FORMAT_YV12A : PIXEL_FORMAT_YV12;
|
|
||||||
|
|
||||||
if (pixel_width_ <= 0 || pixel_height_ <= 0)
|
if (pixel_width_ <= 0 || pixel_height_ <= 0)
|
||||||
return false;
|
return scoped_refptr<VideoStreamInfo>();
|
||||||
|
|
||||||
// Set crop and display unit defaults if these elements are not present.
|
// Set crop and display unit defaults if these elements are not present.
|
||||||
if (crop_bottom_ == -1)
|
if (crop_bottom_ == -1)
|
||||||
|
@ -72,23 +80,28 @@ bool WebMVideoClient::InitializeConfig(
|
||||||
if (display_unit_ == -1)
|
if (display_unit_ == -1)
|
||||||
display_unit_ = 0;
|
display_unit_ = 0;
|
||||||
|
|
||||||
gfx::Size coded_size(pixel_width_, pixel_height_);
|
uint16_t width_after_crop = pixel_width_ - (crop_left_ + crop_right_);
|
||||||
gfx::Rect visible_rect(crop_top_, crop_left_,
|
uint16_t height_after_crop = pixel_height_ - (crop_top_ + crop_bottom_);
|
||||||
pixel_width_ - (crop_left_ + crop_right_),
|
|
||||||
pixel_height_ - (crop_top_ + crop_bottom_));
|
|
||||||
if (display_unit_ == 0) {
|
if (display_unit_ == 0) {
|
||||||
if (display_width_ <= 0)
|
if (display_width_ <= 0)
|
||||||
display_width_ = visible_rect.width();
|
display_width_ = width_after_crop;
|
||||||
if (display_height_ <= 0)
|
if (display_height_ <= 0)
|
||||||
display_height_ = visible_rect.height();
|
display_height_ = height_after_crop;
|
||||||
} else if (display_unit_ == 3) {
|
} else if (display_unit_ == 3) {
|
||||||
if (display_width_ <= 0 || display_height_ <= 0)
|
if (display_width_ <= 0 || display_height_ <= 0)
|
||||||
return false;
|
return scoped_refptr<VideoStreamInfo>();
|
||||||
} else {
|
} else {
|
||||||
LOG(ERROR) << "Unsupported display unit type " << display_unit_;
|
LOG(ERROR) << "Unsupported display unit type " << display_unit_;
|
||||||
return false;
|
return scoped_refptr<VideoStreamInfo>();
|
||||||
}
|
}
|
||||||
gfx::Size natural_size = gfx::Size(display_width_, display_height_);
|
// Calculate sample aspect ratio.
|
||||||
|
int64_t sar_x = display_width_ * height_after_crop;
|
||||||
|
int64_t sar_y = display_height_ * width_after_crop;
|
||||||
|
int64_t gcd = GetGreatestCommonDivisor(sar_x, sar_y);
|
||||||
|
sar_x /= gcd;
|
||||||
|
sar_y /= gcd;
|
||||||
|
|
||||||
const uint8_t* extra_data = NULL;
|
const uint8_t* extra_data = NULL;
|
||||||
size_t extra_data_size = 0;
|
size_t extra_data_size = 0;
|
||||||
if (codec_private.size() > 0) {
|
if (codec_private.size() > 0) {
|
||||||
|
@ -96,10 +109,11 @@ bool WebMVideoClient::InitializeConfig(
|
||||||
extra_data_size = codec_private.size();
|
extra_data_size = codec_private.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
config->Initialize(video_codec, profile, format, COLOR_SPACE_HD_REC709,
|
return scoped_refptr<VideoStreamInfo>(
|
||||||
coded_size, visible_rect, natural_size, extra_data,
|
new VideoStreamInfo(track_num, kWebMTimeScale, 0, video_codec,
|
||||||
extra_data_size, is_encrypted);
|
VideoStreamInfo::GetCodecString(video_codec, 0, 0, 0),
|
||||||
return config->IsValidConfig();
|
"", width_after_crop, height_after_crop, sar_x, sar_y,
|
||||||
|
0, 0, extra_data, extra_data_size, is_encrypted));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebMVideoClient::OnUInt(int id, int64_t val) {
|
bool WebMVideoClient::OnUInt(int id, int64_t val) {
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
|
#include "packager/media/base/video_stream_info.h"
|
||||||
#include "packager/media/formats/webm/webm_parser.h"
|
#include "packager/media/formats/webm/webm_parser.h"
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
|
@ -23,17 +25,17 @@ class WebMVideoClient : public WebMParserClient {
|
||||||
// Reset this object's state so it can process a new video track element.
|
// Reset this object's state so it can process a new video track element.
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
// Initialize |config| with the data in |codec_id|, |codec_private|,
|
// Create a VideoStreamInfo with the data in |track_num|, |codec_id|,
|
||||||
// |is_encrypted| and the fields parsed from the last video track element this
|
// |codec_private|, |is_encrypted| and the fields parsed from the last video
|
||||||
// object was used to parse.
|
// track element this object was used to parse.
|
||||||
// Returns true if |config| was successfully initialized.
|
// Returns a VideoStreamInfo scoped_refptr if successful.
|
||||||
// Returns false if there was unexpected values in the provided parameters or
|
// Returns an empty scoped_refptr if there was unexpected values in the
|
||||||
// video track element fields. The contents of |config| are undefined in this
|
// provided parameters or video track element fields.
|
||||||
// case and should not be relied upon.
|
scoped_refptr<VideoStreamInfo> GetVideoStreamInfo(
|
||||||
bool InitializeConfig(const std::string& codec_id,
|
int64_t track_num,
|
||||||
const std::vector<uint8_t>& codec_private,
|
const std::string& codec_id,
|
||||||
bool is_encrypted,
|
const std::vector<uint8_t>& codec_private,
|
||||||
VideoDecoderConfig* config);
|
bool is_encrypted);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// WebMParserClient implementation.
|
// WebMParserClient implementation.
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
'media/formats/mp2t/mp2t.gyp:mp2t',
|
'media/formats/mp2t/mp2t.gyp:mp2t',
|
||||||
'media/formats/mp4/mp4.gyp:mp4',
|
'media/formats/mp4/mp4.gyp:mp4',
|
||||||
'media/formats/mpeg/mpeg.gyp:mpeg',
|
'media/formats/mpeg/mpeg.gyp:mpeg',
|
||||||
|
'media/formats/webm/webm.gyp:webm',
|
||||||
'media/formats/wvm/wvm.gyp:wvm',
|
'media/formats/wvm/wvm.gyp:wvm',
|
||||||
'mpd/mpd.gyp:mpd_builder',
|
'mpd/mpd.gyp:mpd_builder',
|
||||||
'third_party/boringssl/boringssl.gyp:boringssl',
|
'third_party/boringssl/boringssl.gyp:boringssl',
|
||||||
|
@ -97,6 +98,7 @@
|
||||||
'media/filters/filters.gyp:filters_unittest',
|
'media/filters/filters.gyp:filters_unittest',
|
||||||
'media/formats/mp2t/mp2t.gyp:mp2t_unittest',
|
'media/formats/mp2t/mp2t.gyp:mp2t_unittest',
|
||||||
'media/formats/mp4/mp4.gyp:mp4_unittest',
|
'media/formats/mp4/mp4.gyp:mp4_unittest',
|
||||||
|
'media/formats/webm/webm.gyp:webm_unittest',
|
||||||
'media/formats/wvm/wvm.gyp:wvm_unittest',
|
'media/formats/wvm/wvm.gyp:wvm_unittest',
|
||||||
'mpd/mpd.gyp:mpd_unittest',
|
'mpd/mpd.gyp:mpd_unittest',
|
||||||
'packager_test',
|
'packager_test',
|
||||||
|
|
Loading…
Reference in New Issue