summaryrefslogtreecommitdiff
path: root/chromium/media/filters
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 15:28:34 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:54:51 +0000
commit2a19c63448c84c1805fb1a585c3651318bb86ca7 (patch)
treeeb17888e8531aa6ee5e85721bd553b832a7e5156 /chromium/media/filters
parentb014812705fc80bff0a5c120dfcef88f349816dc (diff)
downloadqtwebengine-chromium-2a19c63448c84c1805fb1a585c3651318bb86ca7.tar.gz
BASELINE: Update Chromium to 69.0.3497.70
Change-Id: I2b7b56e4e7a8b26656930def0d4575dc32b900a0 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/media/filters')
-rw-r--r--chromium/media/filters/android/media_codec_audio_decoder.cc2
-rw-r--r--chromium/media/filters/aom_video_decoder.cc61
-rw-r--r--chromium/media/filters/aom_video_decoder_unittest.cc4
-rw-r--r--chromium/media/filters/audio_file_reader.cc23
-rw-r--r--chromium/media/filters/audio_file_reader_unittest.cc81
-rw-r--r--chromium/media/filters/chunk_demuxer.cc132
-rw-r--r--chromium/media/filters/chunk_demuxer.h56
-rw-r--r--chromium/media/filters/chunk_demuxer_unittest.cc501
-rw-r--r--chromium/media/filters/decoder_stream.cc56
-rw-r--r--chromium/media/filters/decoder_stream.h19
-rw-r--r--chromium/media/filters/decrypting_audio_decoder.cc50
-rw-r--r--chromium/media/filters/decrypting_audio_decoder_unittest.cc35
-rw-r--r--chromium/media/filters/decrypting_demuxer_stream.cc19
-rw-r--r--chromium/media/filters/decrypting_demuxer_stream_unittest.cc14
-rw-r--r--chromium/media/filters/decrypting_video_decoder.cc61
-rw-r--r--chromium/media/filters/decrypting_video_decoder_unittest.cc33
-rw-r--r--chromium/media/filters/demuxer_perftest.cc10
-rw-r--r--chromium/media/filters/ffmpeg_demuxer.cc54
-rw-r--r--chromium/media/filters/ffmpeg_demuxer.h6
-rw-r--r--chromium/media/filters/ffmpeg_demuxer_unittest.cc179
-rw-r--r--chromium/media/filters/ffmpeg_glue_unittest.cc2
-rw-r--r--chromium/media/filters/frame_buffer_pool.cc34
-rw-r--r--chromium/media/filters/frame_processor.cc11
-rw-r--r--chromium/media/filters/frame_processor_unittest.cc7
-rw-r--r--chromium/media/filters/gpu_video_decoder.cc5
-rw-r--r--chromium/media/filters/gpu_video_decoder.h2
-rw-r--r--chromium/media/filters/pipeline_controller.cc8
-rw-r--r--chromium/media/filters/pipeline_controller.h7
-rw-r--r--chromium/media/filters/source_buffer_state.cc166
-rw-r--r--chromium/media/filters/source_buffer_state.h42
-rw-r--r--chromium/media/filters/source_buffer_state_unittest.cc17
-rw-r--r--chromium/media/filters/source_buffer_stream.cc50
-rw-r--r--chromium/media/filters/source_buffer_stream.h10
-rw-r--r--chromium/media/filters/source_buffer_stream_unittest.cc31
-rw-r--r--chromium/media/filters/stream_parser_factory.cc6
-rw-r--r--chromium/media/filters/video_frame_stream_unittest.cc16
-rw-r--r--chromium/media/filters/video_renderer_algorithm.cc10
-rw-r--r--chromium/media/filters/video_renderer_algorithm_unittest.cc15
-rw-r--r--chromium/media/filters/vpx_video_decoder_unittest.cc33
39 files changed, 756 insertions, 1112 deletions
diff --git a/chromium/media/filters/android/media_codec_audio_decoder.cc b/chromium/media/filters/android/media_codec_audio_decoder.cc
index 9429b426ceb..70e1dd2f6b0 100644
--- a/chromium/media/filters/android/media_codec_audio_decoder.cc
+++ b/chromium/media/filters/android/media_codec_audio_decoder.cc
@@ -188,7 +188,7 @@ void MediaCodecAudioDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
input_queue_.push_back(std::make_pair(std::move(buffer), bound_decode_cb));
- codec_loop_->DoPendingWork();
+ codec_loop_->ExpectWork();
}
void MediaCodecAudioDecoder::Reset(const base::Closure& closure) {
diff --git a/chromium/media/filters/aom_video_decoder.cc b/chromium/media/filters/aom_video_decoder.cc
index 41250ae6dad..fa5b8a53ced 100644
--- a/chromium/media/filters/aom_video_decoder.cc
+++ b/chromium/media/filters/aom_video_decoder.cc
@@ -118,61 +118,16 @@ static void SetColorSpaceForFrame(const aom_image_t* img,
return;
}
- ColorSpace color_space = config.color_space();
- gfx::ColorSpace::PrimaryID primaries = gfx::ColorSpace::PrimaryID::INVALID;
- gfx::ColorSpace::TransferID transfer = gfx::ColorSpace::TransferID::INVALID;
- gfx::ColorSpace::MatrixID matrix = gfx::ColorSpace::MatrixID::INVALID;
gfx::ColorSpace::RangeID range = img->range == AOM_CR_FULL_RANGE
? gfx::ColorSpace::RangeID::FULL
: gfx::ColorSpace::RangeID::LIMITED;
- switch (img->cs) {
- case AOM_CS_BT_601:
- case AOM_CS_SMPTE_170:
- primaries = gfx::ColorSpace::PrimaryID::SMPTE170M;
- transfer = gfx::ColorSpace::TransferID::SMPTE170M;
- matrix = gfx::ColorSpace::MatrixID::SMPTE170M;
- color_space = COLOR_SPACE_SD_REC601;
- break;
- case AOM_CS_SMPTE_240:
- primaries = gfx::ColorSpace::PrimaryID::SMPTE240M;
- transfer = gfx::ColorSpace::TransferID::SMPTE240M;
- matrix = gfx::ColorSpace::MatrixID::SMPTE240M;
- break;
- case AOM_CS_BT_709:
- primaries = gfx::ColorSpace::PrimaryID::BT709;
- transfer = gfx::ColorSpace::TransferID::BT709;
- matrix = gfx::ColorSpace::MatrixID::BT709;
- color_space = COLOR_SPACE_HD_REC709;
- break;
- case AOM_CS_BT_2020_NCL:
- case AOM_CS_BT_2020_CL:
- primaries = gfx::ColorSpace::PrimaryID::BT2020;
- if (img->bit_depth >= 12) {
- transfer = gfx::ColorSpace::TransferID::BT2020_12;
- } else if (img->bit_depth >= 10) {
- transfer = gfx::ColorSpace::TransferID::BT2020_10;
- } else {
- transfer = gfx::ColorSpace::TransferID::BT709;
- }
- matrix = img->cs == AOM_CS_BT_2020_NCL
- ? gfx::ColorSpace::MatrixID::BT2020_NCL
- : gfx::ColorSpace::MatrixID::BT2020_CL;
- break;
- case AOM_CS_SRGB:
- primaries = gfx::ColorSpace::PrimaryID::BT709;
- transfer = gfx::ColorSpace::TransferID::IEC61966_2_1;
- matrix = gfx::ColorSpace::MatrixID::BT709;
- break;
- default:
- NOTIMPLEMENTED() << "Unsupported color space encountered: " << img->cs;
- break;
- }
-
- // TODO(ccameron): Set a color space even for unspecified values.
- if (primaries != gfx::ColorSpace::PrimaryID::INVALID)
- frame->set_color_space(gfx::ColorSpace(primaries, transfer, matrix, range));
- frame->metadata()->SetInteger(VideoFrameMetadata::COLOR_SPACE, color_space);
+ // AOM color space defines match ISO 23001-8:2016 via ISO/IEC 23091-4/ITU-T
+ // H.273.
+ // http://av1-spec.argondesign.com/av1-spec/av1-spec.html#color-config-semantics
+ frame->set_color_space(
+ media::VideoColorSpace(img->cp, img->tc, img->mc, range)
+ .ToGfxColorSpace());
}
// Copies plane of 8-bit pixels out of a 16-bit values.
@@ -308,8 +263,8 @@ bool AomVideoDecoder::DecodeBuffer(const DecoderBuffer* buffer) {
if (aom_codec_decode(
aom_decoder_.get(), buffer->data(), buffer->data_size(),
- reinterpret_cast<void*>(buffer->timestamp().InMicroseconds()),
- 0 /* deadline */) != AOM_CODEC_OK) {
+ reinterpret_cast<void*>(buffer->timestamp().InMicroseconds())) !=
+ AOM_CODEC_OK) {
const char* detail = aom_codec_error_detail(aom_decoder_.get());
MEDIA_LOG(ERROR, media_log_)
<< "aom_codec_decode() failed: " << aom_codec_error(aom_decoder_.get())
diff --git a/chromium/media/filters/aom_video_decoder_unittest.cc b/chromium/media/filters/aom_video_decoder_unittest.cc
index 7ab2b07ad95..f48a31f640b 100644
--- a/chromium/media/filters/aom_video_decoder_unittest.cc
+++ b/chromium/media/filters/aom_video_decoder_unittest.cc
@@ -33,7 +33,7 @@ class AomVideoDecoderTest : public testing::Test {
public:
AomVideoDecoderTest()
: decoder_(new AomVideoDecoder(&media_log_)),
- i_frame_buffer_(ReadTestDataFile("av1-I-frame-352x288")) {}
+ i_frame_buffer_(ReadTestDataFile("av1-I-frame-320x240")) {}
~AomVideoDecoderTest() override { Destroy(); }
@@ -208,7 +208,7 @@ TEST_F(AomVideoDecoderTest, DecodeFrame_Normal) {
// the output size was adjusted.
// TODO(dalecurtis): Get an I-frame from a larger video.
TEST_F(AomVideoDecoderTest, DISABLED_DecodeFrame_LargerWidth) {
- DecodeIFrameThenTestFile("av1-I-frame-352x288", gfx::Size(1280, 720));
+ DecodeIFrameThenTestFile("av1-I-frame-320x240", gfx::Size(1280, 720));
}
// Decode a VP9 frame which should trigger a decoder error.
diff --git a/chromium/media/filters/audio_file_reader.cc b/chromium/media/filters/audio_file_reader.cc
index ae37ab7b375..ded5a7d200f 100644
--- a/chromium/media/filters/audio_file_reader.cc
+++ b/chromium/media/filters/audio_file_reader.cc
@@ -215,7 +215,7 @@ bool AudioFileReader::OnNewFrame(
int* total_frames,
std::vector<std::unique_ptr<AudioBus>>* decoded_audio_packets,
AVFrame* frame) {
- const int frames_read = frame->nb_samples;
+ int frames_read = frame->nb_samples;
if (frames_read < 0)
return false;
@@ -233,6 +233,27 @@ bool AudioFileReader::OnNewFrame(
return false;
}
+ // AAC decoding doesn't properly trim the last packet in a stream, so if we
+ // have duration information, use it to set the correct length to avoid extra
+ // silence from being output. In the case where we are also discarding some
+ // portion of the packet (as indicated by a negative pts), we further want to
+ // adjust the duration downward by however much exists before zero.
+ if (audio_codec_ == kCodecAAC && frame->pkt_duration) {
+ const base::TimeDelta pkt_duration = ConvertFromTimeBase(
+ glue_->format_context()->streams[stream_index_]->time_base,
+ frame->pkt_duration + std::min(static_cast<int64_t>(0), frame->pts));
+ const base::TimeDelta frame_duration = base::TimeDelta::FromSecondsD(
+ frames_read / static_cast<double>(sample_rate_));
+
+ if (pkt_duration < frame_duration && pkt_duration > base::TimeDelta()) {
+ const int new_frames_read = frames_read * (pkt_duration.InSecondsF() /
+ frame_duration.InSecondsF());
+ DVLOG(2) << "Shrinking AAC frame from " << frames_read << " to "
+ << new_frames_read << " based on packet duration.";
+ frames_read = new_frames_read;
+ }
+ }
+
// Deinterleave each channel and convert to 32bit floating-point with
// nominal range -1.0 -> +1.0. If the output is already in float planar
// format, just copy it into the AudioBus.
diff --git a/chromium/media/filters/audio_file_reader_unittest.cc b/chromium/media/filters/audio_file_reader_unittest.cc
index 6df10b2a8fd..f8d4b839243 100644
--- a/chromium/media/filters/audio_file_reader_unittest.cc
+++ b/chromium/media/filters/audio_file_reader_unittest.cc
@@ -125,9 +125,7 @@ class AudioFileReaderTest : public testing::Test {
EXPECT_EQ(reader_->Read(&decoded_audio_packets), 0);
}
- void disable_packet_verification() {
- packet_verification_disabled_ = true;
- }
+ void disable_packet_verification() { packet_verification_disabled_ = true; }
protected:
scoped_refptr<DecoderBuffer> data_;
@@ -162,72 +160,52 @@ TEST_F(AudioFileReaderTest, Vorbis) {
}
TEST_F(AudioFileReaderTest, WaveU8) {
- RunTest("sfx_u8.wav",
- "-1.23,-1.57,-1.14,-0.91,-0.87,-0.07,",
- 1,
- 44100,
- base::TimeDelta::FromMicroseconds(288414),
- 12720,
- 12719);
+ RunTest("sfx_u8.wav", "-1.23,-1.57,-1.14,-0.91,-0.87,-0.07,", 1, 44100,
+ base::TimeDelta::FromMicroseconds(288414), 12720, 12719);
}
TEST_F(AudioFileReaderTest, WaveS16LE) {
- RunTest("sfx_s16le.wav",
- "3.05,2.87,3.00,3.32,3.58,4.08,",
- 1,
- 44100,
- base::TimeDelta::FromMicroseconds(288414),
- 12720,
- 12719);
+ RunTest("sfx_s16le.wav", "3.05,2.87,3.00,3.32,3.58,4.08,", 1, 44100,
+ base::TimeDelta::FromMicroseconds(288414), 12720, 12719);
}
TEST_F(AudioFileReaderTest, WaveS24LE) {
- RunTest("sfx_s24le.wav",
- "3.03,2.86,2.99,3.31,3.57,4.06,",
- 1,
- 44100,
- base::TimeDelta::FromMicroseconds(288414),
- 12720,
- 12719);
+ RunTest("sfx_s24le.wav", "3.03,2.86,2.99,3.31,3.57,4.06,", 1, 44100,
+ base::TimeDelta::FromMicroseconds(288414), 12720, 12719);
}
TEST_F(AudioFileReaderTest, WaveF32LE) {
- RunTest("sfx_f32le.wav",
- "3.03,2.86,2.99,3.31,3.57,4.06,",
- 1,
- 44100,
- base::TimeDelta::FromMicroseconds(288414),
- 12720,
- 12719);
+ RunTest("sfx_f32le.wav", "3.03,2.86,2.99,3.31,3.57,4.06,", 1, 44100,
+ base::TimeDelta::FromMicroseconds(288414), 12720, 12719);
}
TEST_F(AudioFileReaderTest, MP3) {
- RunTest("sfx.mp3",
- "1.30,2.72,4.56,5.08,3.74,2.03,",
- 1,
- 44100,
- base::TimeDelta::FromMicroseconds(313470),
- 13825,
- 11025);
+ RunTest("sfx.mp3", "1.30,2.72,4.56,5.08,3.74,2.03,", 1, 44100,
+ base::TimeDelta::FromMicroseconds(313470), 13825, 11025);
}
TEST_F(AudioFileReaderTest, CorruptMP3) {
// Disable packet verification since the file is corrupt and FFmpeg does not
// make any guarantees on packet consistency in this case.
disable_packet_verification();
- RunTest("corrupt.mp3",
- "-4.95,-2.95,-0.44,1.16,0.31,-2.21,",
- 1,
- 44100,
- base::TimeDelta::FromMicroseconds(1018801),
- 44930,
- 44928);
+ RunTest("corrupt.mp3", "-4.95,-2.95,-0.44,1.16,0.31,-2.21,", 1, 44100,
+ base::TimeDelta::FromMicroseconds(1018801), 44930, 44928);
}
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
TEST_F(AudioFileReaderTest, AAC) {
- RunTest("sfx.m4a", "1.81,1.66,2.32,3.27,4.46,3.36,", 1, 44100,
- base::TimeDelta::FromMicroseconds(371660), 16391, 13312);
+ RunTest("sfx.m4a", "0.79,2.31,4.15,4.92,4.04,1.44,", 1, 44100,
+ base::TimeDelta::FromMicroseconds(371660), 16391, 12701);
+}
+
+TEST_F(AudioFileReaderTest, AAC_SinglePacket) {
+ RunTest("440hz-10ms.m4a", "3.77,4.53,4.75,3.48,3.67,3.76,", 1, 44100,
+ base::TimeDelta::FromMicroseconds(69660), 3073, 441);
+}
+
+TEST_F(AudioFileReaderTest, AAC_ADTS) {
+ RunTest("sfx.adts", "1.80,1.66,2.31,3.26,4.46,3.36,", 1, 44100,
+ base::TimeDelta::FromMicroseconds(2825180), 124591, 13312);
}
TEST_F(AudioFileReaderTest, MidStreamConfigChangesFail) {
@@ -240,13 +218,8 @@ TEST_F(AudioFileReaderTest, VorbisInvalidChannelLayout) {
}
TEST_F(AudioFileReaderTest, WaveValidFourChannelLayout) {
- RunTest("4ch.wav",
- "131.71,38.02,130.31,44.89,135.98,42.52,",
- 4,
- 44100,
- base::TimeDelta::FromMicroseconds(100001),
- 4411,
- 4410);
+ RunTest("4ch.wav", "131.71,38.02,130.31,44.89,135.98,42.52,", 4, 44100,
+ base::TimeDelta::FromMicroseconds(100001), 4411, 4410);
}
} // namespace media
diff --git a/chromium/media/filters/chunk_demuxer.cc b/chromium/media/filters/chunk_demuxer.cc
index 50fc1bc8ba5..230c3fbad5a 100644
--- a/chromium/media/filters/chunk_demuxer.cc
+++ b/chromium/media/filters/chunk_demuxer.cc
@@ -52,6 +52,37 @@ using base::TimeDelta;
} \
}
+namespace {
+
+// Helper to attempt construction of a StreamParser specific to |content_type|
+// and |codecs|.
+// TODO(wolenetz): Consider relocating this to StreamParserFactory in
+// conjunction with updating StreamParserFactory's isTypeSupported() to also
+// parse codecs, rather than require preparsed vector.
+std::unique_ptr<media::StreamParser> CreateParserForTypeAndCodecs(
+ const std::string& content_type,
+ const std::string& codecs,
+ media::MediaLog* media_log) {
+ std::vector<std::string> parsed_codec_ids;
+ media::SplitCodecsToVector(codecs, &parsed_codec_ids, false);
+ return media::StreamParserFactory::Create(content_type, parsed_codec_ids,
+ media_log);
+}
+
+// Helper to calculate the expected codecs parsed from initialization segments
+// for a few mime types that have an implicit codec.
+std::string ExpectedCodecs(const std::string& content_type,
+ const std::string& codecs) {
+ if (codecs == "" && content_type == "audio/aac")
+ return "aac";
+ if (codecs == "" &&
+ (content_type == "audio/mpeg" || content_type == "audio/mp3"))
+ return "mp3";
+ return codecs;
+}
+
+} // namespace
+
namespace media {
ChunkDemuxerStream::ChunkDemuxerStream(Type type,
@@ -228,6 +259,7 @@ void ChunkDemuxerStream::OnStartOfCodedFrameGroup(DecodeTimestamp start_dts,
}
bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config,
+ bool allow_codec_change,
MediaLog* media_log) {
DCHECK(config.IsValidConfig());
DCHECK_EQ(type_, AUDIO);
@@ -245,10 +277,11 @@ bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config,
return true;
}
- return SBSTREAM_OP(UpdateAudioConfig(config));
+ return SBSTREAM_OP(UpdateAudioConfig(config, allow_codec_change));
}
bool ChunkDemuxerStream::UpdateVideoConfig(const VideoDecoderConfig& config,
+ bool allow_codec_change,
MediaLog* media_log) {
DCHECK(config.IsValidConfig());
DCHECK_EQ(type_, VIDEO);
@@ -260,7 +293,7 @@ bool ChunkDemuxerStream::UpdateVideoConfig(const VideoDecoderConfig& config,
return true;
}
- return SBSTREAM_OP(UpdateVideoConfig(config));
+ return SBSTREAM_OP(UpdateVideoConfig(config, allow_codec_change));
}
void ChunkDemuxerStream::UpdateTextConfig(const TextTrackConfig& config,
@@ -440,7 +473,6 @@ ChunkDemuxer::ChunkDemuxer(
open_cb_(open_cb),
progress_cb_(progress_cb),
encrypted_media_init_data_cb_(encrypted_media_init_data_cb),
- enable_text_(false),
media_log_(media_log),
duration_(kNoTimestamp),
user_specified_duration_(-1),
@@ -461,8 +493,7 @@ std::string ChunkDemuxer::GetDisplayName() const {
}
void ChunkDemuxer::Initialize(DemuxerHost* host,
- const PipelineStatusCB& init_cb,
- bool enable_text_tracks) {
+ const PipelineStatusCB& init_cb) {
DVLOG(1) << "Init(), buffering_by_pts_=" << buffering_by_pts_;
base::AutoLock auto_lock(lock_);
@@ -480,7 +511,6 @@ void ChunkDemuxer::Initialize(DemuxerHost* host,
// has a chance to run. This is because ChunkDemuxer::ReportError_Locked
// directly calls DemuxerHost::OnDemuxerError: crbug.com/633016.
init_cb_ = init_cb;
- enable_text_ = enable_text_tracks;
ChangeState_Locked(INITIALIZING);
@@ -617,9 +647,9 @@ void ChunkDemuxer::CancelPendingSeek(TimeDelta seek_time) {
}
ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id,
- const std::string& type,
+ const std::string& content_type,
const std::string& codecs) {
- DVLOG(1) << __func__ << " id=" << id << " mime_type=" << type
+ DVLOG(1) << __func__ << " id=" << id << " content_type=" << content_type
<< " codecs=" << codecs;
base::AutoLock auto_lock(lock_);
@@ -630,14 +660,10 @@ ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id,
// needed. See https://crbug.com/786975.
CHECK(!init_cb_.is_null());
- std::vector<std::string> parsed_codec_ids;
- media::SplitCodecsToVector(codecs, &parsed_codec_ids, false);
-
std::unique_ptr<media::StreamParser> stream_parser(
- StreamParserFactory::Create(type, parsed_codec_ids, media_log_));
-
+ CreateParserForTypeAndCodecs(content_type, codecs, media_log_));
if (!stream_parser) {
- DVLOG(1) << __func__ << " failed: unsupported mime_type=" << type
+ DVLOG(1) << __func__ << " failed: unsupported content_type=" << content_type
<< " codecs=" << codecs;
return ChunkDemuxer::kNotSupported;
}
@@ -657,11 +683,6 @@ ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id,
SourceBufferState::NewTextTrackCB new_text_track_cb;
- if (enable_text_) {
- new_text_track_cb = base::Bind(&ChunkDemuxer::OnNewTextTrack,
- base::Unretained(this));
- }
-
// TODO(wolenetz): Change these to DCHECKs or switch to returning
// kReachedIdLimit once less verification in release build is needed. See
// https://crbug.com/786975.
@@ -671,15 +692,10 @@ ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id,
CHECK(*insert_result.first == id);
CHECK(insert_result.second); // Only true if insertion succeeded.
- std::string expected_sbs_codecs = codecs;
- if (codecs == "" && type == "audio/aac")
- expected_sbs_codecs = "aac";
- if (codecs == "" && (type == "audio/mpeg" || type == "audio/mp3"))
- expected_sbs_codecs = "mp3";
-
- source_state->Init(
- base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this), id),
- expected_sbs_codecs, encrypted_media_init_data_cb_, new_text_track_cb);
+ source_state->Init(base::BindOnce(&ChunkDemuxer::OnSourceInitDone,
+ base::Unretained(this), id),
+ ExpectedCodecs(content_type, codecs),
+ encrypted_media_init_data_cb_, new_text_track_cb);
// TODO(wolenetz): Change to DCHECKs once less verification in release build
// is needed. See https://crbug.com/786975.
@@ -947,6 +963,51 @@ void ChunkDemuxer::Remove(const std::string& id, TimeDelta start,
host_->OnBufferedTimeRangesChanged(GetBufferedRanges_Locked());
}
+bool ChunkDemuxer::CanChangeType(const std::string& id,
+ const std::string& content_type,
+ const std::string& codecs) {
+ // Note, Chromium currently will not compare content_type and codecs, if any,
+ // with previous content_type and codecs of the SourceBuffer.
+ // TODO(wolenetz): Consider returning false if the codecs parameters are ever
+ // made to be precise such that they signal that the number of tracks of
+ // various media types differ from the first initialization segment (if
+ // received already). Switching to an audio-only container, when the first
+ // initialization segment only contained non-audio tracks, is one example we
+ // could enforce earlier here.
+
+ DVLOG(1) << __func__ << " id=" << id << " content_type=" << content_type
+ << " codecs=" << codecs;
+ base::AutoLock auto_lock(lock_);
+
+ DCHECK(IsValidId(id));
+
+ // CanChangeType() doesn't care if there has or hasn't been received a first
+ // initialization segment for the source buffer corresponding to |id|.
+
+ std::unique_ptr<media::StreamParser> stream_parser(
+ CreateParserForTypeAndCodecs(content_type, codecs, media_log_));
+ return !!stream_parser;
+}
+
+void ChunkDemuxer::ChangeType(const std::string& id,
+ const std::string& content_type,
+ const std::string& codecs) {
+ DVLOG(1) << __func__ << " id=" << id << " content_type=" << content_type
+ << " codecs=" << codecs;
+
+ base::AutoLock auto_lock(lock_);
+
+ DCHECK(state_ == INITIALIZING || state_ == INITIALIZED) << state_;
+ DCHECK(IsValidId(id));
+
+ std::unique_ptr<media::StreamParser> stream_parser(
+ CreateParserForTypeAndCodecs(content_type, codecs, media_log_));
+ // Caller should query CanChangeType() first to protect from failing this.
+ DCHECK(stream_parser);
+ source_state_map_[id]->ChangeType(std::move(stream_parser),
+ ExpectedCodecs(content_type, codecs));
+}
+
double ChunkDemuxer::GetDuration() {
base::AutoLock auto_lock(lock_);
return GetDuration_Locked();
@@ -1018,6 +1079,14 @@ bool ChunkDemuxer::IsParsingMediaSegment(const std::string& id) {
return source_state_map_[id]->parsing_media_segment();
}
+bool ChunkDemuxer::GetGenerateTimestampsFlag(const std::string& id) {
+ base::AutoLock auto_lock(lock_);
+ DVLOG(1) << "GetGenerateTimestampsFlag(" << id << ")";
+ CHECK(IsValidId(id));
+
+ return source_state_map_[id]->generate_timestamps_flag();
+}
+
void ChunkDemuxer::SetSequenceMode(const std::string& id,
bool sequence_mode) {
base::AutoLock auto_lock(lock_);
@@ -1312,13 +1381,6 @@ ChunkDemuxerStream* ChunkDemuxer::CreateDemuxerStream(
return owning_vector->back().get();
}
-void ChunkDemuxer::OnNewTextTrack(ChunkDemuxerStream* text_stream,
- const TextTrackConfig& config) {
- lock_.AssertAcquired();
- DCHECK_NE(state_, SHUTDOWN);
- host_->AddTextStream(text_stream, config);
-}
-
bool ChunkDemuxer::IsValidId(const std::string& source_id) const {
lock_.AssertAcquired();
return source_state_map_.count(source_id) > 0u;
diff --git a/chromium/media/filters/chunk_demuxer.h b/chromium/media/filters/chunk_demuxer.h
index 9253d2d50a5..d4fdfb4c7e3 100644
--- a/chromium/media/filters/chunk_demuxer.h
+++ b/chromium/media/filters/chunk_demuxer.h
@@ -103,10 +103,16 @@ class MEDIA_EXPORT ChunkDemuxerStream : public DemuxerStream {
base::TimeDelta start_pts);
// Called when midstream config updates occur.
+ // For audio and video, if the codec is allowed to change, the caller should
+ // set |allow_codec_change| to true.
// Returns true if the new config is accepted.
// Returns false if the new config should trigger an error.
- bool UpdateAudioConfig(const AudioDecoderConfig& config, MediaLog* media_log);
- bool UpdateVideoConfig(const VideoDecoderConfig& config, MediaLog* media_log);
+ bool UpdateAudioConfig(const AudioDecoderConfig& config,
+ bool allow_codec_change,
+ MediaLog* media_log);
+ bool UpdateVideoConfig(const VideoDecoderConfig& config,
+ bool allow_codec_change,
+ MediaLog* media_log);
void UpdateTextConfig(const TextTrackConfig& config, MediaLog* media_log);
void MarkEndOfStream();
@@ -200,9 +206,7 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
// |enable_text| Process inband text tracks in the normal way when true,
// otherwise ignore them.
- void Initialize(DemuxerHost* host,
- const PipelineStatusCB& init_cb,
- bool enable_text_tracks) override;
+ void Initialize(DemuxerHost* host, const PipelineStatusCB& init_cb) override;
void Stop() override;
void Seek(base::TimeDelta time, const PipelineStatusCB& cb) override;
base::Time GetTimelineOffset() const override;
@@ -218,15 +222,16 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
void StartWaitingForSeek(base::TimeDelta seek_time) override;
void CancelPendingSeek(base::TimeDelta seek_time) override;
- // Registers a new |id| to use for AppendData() calls. |type| indicates
- // the MIME type for the data that we intend to append for this ID.
- // kOk is returned if the demuxer has enough resources to support another ID
- // and supports the format indicated by |type|.
- // kNotSupported is returned if |type| is not a supported format.
- // kReachedIdLimit is returned if the demuxer cannot handle another ID right
- // now.
+ // Registers a new |id| to use for AppendData() calls. |content_type|
+ // indicates the MIME type's ContentType and |codecs| indicates the MIME
+ // type's "codecs" parameter string (if any) for the data that we intend to
+ // append for this ID. kOk is returned if the demuxer has enough resources to
+ // support another ID and supports the format indicated by |content_type| and
+ // |codecs|. kReachedIdLimit is returned if the demuxer cannot handle another
+ // ID right now. kNotSupported is returned if |content_type| and |codecs| is
+ // not a supported format.
Status AddId(const std::string& id,
- const std::string& type,
+ const std::string& content_type,
const std::string& codecs);
// Notifies a caller via |tracks_updated_cb| that the set of media tracks
@@ -285,6 +290,26 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
void Remove(const std::string& id, base::TimeDelta start,
base::TimeDelta end);
+ // Returns whether or not the source buffer associated with |id| can change
+ // its parser type to one which parses |content_type| and |codecs|.
+ // |content_type| indicates the ContentType of the MIME type for the data that
+ // we intend to append for this |id|; |codecs| similarly indicates the MIME
+ // type's "codecs" parameter, if any.
+ bool CanChangeType(const std::string& id,
+ const std::string& content_type,
+ const std::string& codecs);
+
+ // For the source buffer associated with |id|, changes its parser type to one
+ // which parses |content_type| and |codecs|. |content_type| indicates the
+ // ContentType of the MIME type for the data that we intend to append for this
+ // |id|; |codecs| similarly indicates the MIME type's "codecs" parameter, if
+ // any. Caller must first ensure CanChangeType() returns true for the same
+ // parameters. Caller must also ensure that ResetParserState() is done before
+ // calling this, to flush any pending frames.
+ void ChangeType(const std::string& id,
+ const std::string& content_type,
+ const std::string& codecs);
+
// If the buffer is full, attempts to try to free up space, as specified in
// the "Coded Frame Eviction Algorithm" in the Media Source Extensions Spec.
// Returns false iff buffer is still full after running eviction.
@@ -310,6 +335,10 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
// a media segment, or false otherwise.
bool IsParsingMediaSegment(const std::string& id);
+ // Returns the 'Generate Timestamps Flag', as described in the MSE Byte Stream
+ // Format Registry, for the source buffer associated with |id|.
+ bool GetGenerateTimestampsFlag(const std::string& id);
+
// Set the append mode to be applied to subsequent buffers appended to the
// source buffer associated with |id|. If |sequence_mode| is true, caller
// is requesting "sequence" mode. Otherwise, caller is requesting "segments"
@@ -430,7 +459,6 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
base::Closure open_cb_;
base::Closure progress_cb_;
EncryptedMediaInitDataCB encrypted_media_init_data_cb_;
- bool enable_text_;
// MediaLog for reporting messages and properties to debug content and engine.
MediaLog* media_log_;
diff --git a/chromium/media/filters/chunk_demuxer_unittest.cc b/chromium/media/filters/chunk_demuxer_unittest.cc
index 53adadf198c..57ed2458fe5 100644
--- a/chromium/media/filters/chunk_demuxer_unittest.cc
+++ b/chromium/media/filters/chunk_demuxer_unittest.cc
@@ -97,7 +97,6 @@ const int kVideoTrackEntryHeaderSize =
const int kVideoTrackNum = 1;
const int kAudioTrackNum = 2;
-const int kTextTrackNum = 3;
const int kAlternateVideoTrackNum = 4;
const int kAlternateAudioTrackNum = 5;
const int kAlternateTextTrackNum = 6;
@@ -209,8 +208,9 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
base::Bind(&ChunkDemuxerTest::DemuxerOpened, base::Unretained(this));
base::Closure progress_cb =
base::Bind(&ChunkDemuxerTest::OnProgress, base::Unretained(this));
- Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb = base::Bind(
- &ChunkDemuxerTest::OnEncryptedMediaInitData, base::Unretained(this));
+ Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
+ base::BindRepeating(&ChunkDemuxerTest::OnEncryptedMediaInitData,
+ base::Unretained(this));
EXPECT_MEDIA_LOG(
BufferingByPtsDts(buffering_api_ == BufferingApi::kNewByPts));
demuxer_.reset(new ChunkDemuxer(open_cb, progress_cb,
@@ -228,7 +228,6 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
int* size) {
bool has_audio = (stream_flags & HAS_AUDIO) != 0;
bool has_video = (stream_flags & HAS_VIDEO) != 0;
- bool has_text = (stream_flags & HAS_TEXT) != 0;
scoped_refptr<DecoderBuffer> ebml_header;
scoped_refptr<DecoderBuffer> info;
scoped_refptr<DecoderBuffer> audio_track_entry;
@@ -279,32 +278,6 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
}
}
- if (has_text) {
- // TODO(matthewjheaney): create an abstraction to do
- // this (http://crbug/321454).
- // We need it to also handle the creation of multiple text tracks.
- //
- // This is the track entry for a text track,
- // TrackEntry [AE], size=30
- // TrackNum [D7], size=1, val=3 (or 4 if USE_ALTERNATE_TEXT_TRACK_ID)
- // TrackUID [73] [C5], size=1, value=3 (must remain constant for same
- // track, even if TrackNum changes)
- // TrackType [83], size=1, val=0x11
- // CodecId [86], size=18, val="D_WEBVTT/SUBTITLES"
- char str[] = "\xAE\x9E\xD7\x81\x03\x73\xC5\x81\x03"
- "\x83\x81\x11\x86\x92"
- "D_WEBVTT/SUBTITLES";
- DCHECK_EQ(str[4], kTextTrackNum);
- if (stream_flags & USE_ALTERNATE_TEXT_TRACK_ID)
- str[4] = kAlternateTextTrackNum;
-
- const int len = strlen(str);
- DCHECK_EQ(len, 32);
- const uint8_t* const buf = reinterpret_cast<const uint8_t*>(str);
- text_track_entry = DecoderBuffer::CopyFrom(buf, len);
- tracks_element_size += text_track_entry->data_size();
- }
-
*size = ebml_header->data_size() + info->data_size() +
kTracksHeaderSize + tracks_element_size;
@@ -353,12 +326,6 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
}
buf += audio_track_entry->data_size();
}
-
- if (has_text) {
- memcpy(buf, text_track_entry->data(),
- text_track_entry->data_size());
- buf += text_track_entry->data_size();
- }
}
ChunkDemuxer::Status AddId() {
@@ -433,7 +400,6 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
case kAlternateAudioTrackNum:
block_duration = kAudioBlockDuration;
break;
- case kTextTrackNum: // Fall-through.
case kAlternateTextTrackNum:
block_duration = kTextBlockDuration;
break;
@@ -513,8 +479,7 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
CHECK(base::StringToInt(timestamp_str, &block_info.timestamp_in_ms));
- if (track_number == kTextTrackNum ||
- track_number == kAlternateTextTrackNum) {
+ if (track_number == kAlternateTextTrackNum) {
block_info.duration = kTextBlockDuration;
ASSERT_EQ(kWebMFlagKeyframe, block_info.flags)
<< "Text block with timestamp " << block_info.timestamp_in_ms
@@ -727,7 +692,6 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
enum StreamFlags {
HAS_AUDIO = 1 << 0,
HAS_VIDEO = 1 << 1,
- HAS_TEXT = 1 << 2,
USE_ALTERNATE_AUDIO_TRACK_ID = 1 << 3,
USE_ALTERNATE_VIDEO_TRACK_ID = 1 << 4,
USE_ALTERNATE_TEXT_TRACK_ID = 1 << 5,
@@ -788,8 +752,8 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
EXPECT_MEDIA_LOG(StreamParsingFailed());
}
- demuxer_->Initialize(
- &host_, CreateInitDoneCB(expected_duration, expected_status), true);
+ demuxer_->Initialize(&host_,
+ CreateInitDoneCB(expected_duration, expected_status));
if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk)
return false;
@@ -799,11 +763,10 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
}
bool InitDemuxerAudioAndVideoSourcesText(const std::string& audio_id,
- const std::string& video_id,
- bool has_text) {
+ const std::string& video_id) {
EXPECT_CALL(*this, DemuxerOpened());
- demuxer_->Initialize(
- &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
+ demuxer_->Initialize(&host_,
+ CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
if (AddId(audio_id, HAS_AUDIO) != ChunkDemuxer::kOk)
return false;
@@ -813,11 +776,6 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
int audio_flags = HAS_AUDIO;
int video_flags = HAS_VIDEO;
- if (has_text) {
- audio_flags |= HAS_TEXT;
- video_flags |= HAS_TEXT;
- }
-
// Note: Unlike InitDemuxerWithEncryptionInfo, this method is currently
// incompatible with InSequence tests. Refactoring of the duration
// set expectation to not be added during CreateInitDoneCB() could fix this.
@@ -833,7 +791,7 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
bool InitDemuxerAudioAndVideoSources(const std::string& audio_id,
const std::string& video_id) {
- return InitDemuxerAudioAndVideoSourcesText(audio_id, video_id, false);
+ return InitDemuxerAudioAndVideoSourcesText(audio_id, video_id);
}
// Initializes the demuxer with data from 2 files with different
@@ -864,8 +822,8 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
ExpectInitMediaLogs(HAS_AUDIO | HAS_VIDEO);
EXPECT_CALL(*this, InitSegmentReceivedMock(_));
demuxer_->Initialize(
- &host_, CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744),
- PIPELINE_OK), true);
+ &host_,
+ CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744), PIPELINE_OK));
if (AddId(kSourceId, HAS_AUDIO | HAS_VIDEO) != ChunkDemuxer::kOk)
return false;
@@ -874,7 +832,7 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(2)).Times(7);
// Expect duration adjustment since actual duration differs slightly from
// duration in the init segment.
- EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2746)));
+ EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2768)));
EXPECT_TRUE(AppendData(bear1->data(), bear1->data_size()));
// Last audio frame has timestamp 2721 and duration 24 (estimated from max
// seen so far for audio track).
@@ -901,7 +859,7 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
// segment.
EXPECT_CALL(*this, InitSegmentReceivedMock(_));
EXPECT_TRUE(AppendData(bear1->data(), 4370));
- EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(23));
+ EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(24));
EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(779000, 759000, 3000));
EXPECT_TRUE(AppendData(bear1->data() + 72737, 28183));
CheckExpectedRanges("{ [0,2736) }");
@@ -1235,8 +1193,7 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
const base::TimeDelta& duration,
int stream_flags) {
EXPECT_CALL(*this, DemuxerOpened());
- demuxer_->Initialize(
- &host_, CreateInitDoneCB(duration, PIPELINE_OK), true);
+ demuxer_->Initialize(&host_, CreateInitDoneCB(duration, PIPELINE_OK));
if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk)
return false;
@@ -1244,6 +1201,7 @@ class ChunkDemuxerTest : public ::testing::TestWithParam<BufferingApi> {
// Read a WebM file into memory and send the data to the demuxer.
scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
EXPECT_CALL(*this, InitSegmentReceivedMock(_));
+
EXPECT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512));
// Verify that the timestamps on the first few packets match what we
@@ -1428,123 +1386,6 @@ TEST_P(ChunkDemuxerTest, Init) {
}
}
-// TODO(acolwell): Fold this test into Init tests since the tests are
-// almost identical.
-TEST_P(ChunkDemuxerTest, InitText) {
- // Test with 1 video stream and 1 text streams, and 0 or 1 audio streams.
- // No encryption cases handled here.
- bool has_video = true;
- bool is_audio_encrypted = false;
- bool is_video_encrypted = false;
- for (int i = 0; i < 2; i++) {
- bool has_audio = (i & 0x1) != 0;
-
- CreateNewDemuxer();
-
- DemuxerStream* text_stream = NULL;
- TextTrackConfig text_config;
- EXPECT_CALL(host_, AddTextStream(_, _))
- .WillOnce(DoAll(SaveArg<0>(&text_stream),
- SaveArg<1>(&text_config)));
-
- int stream_flags = HAS_TEXT;
- if (has_audio)
- stream_flags |= HAS_AUDIO;
-
- if (has_video)
- stream_flags |= HAS_VIDEO;
-
- ASSERT_TRUE(InitDemuxerWithEncryptionInfo(
- stream_flags, is_audio_encrypted, is_video_encrypted));
- ASSERT_TRUE(text_stream);
- EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
- EXPECT_EQ(kTextSubtitles, text_config.kind());
- EXPECT_FALSE(static_cast<ChunkDemuxerStream*>(text_stream)
- ->supports_partial_append_window_trimming());
-
- DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
- if (has_audio) {
- ASSERT_TRUE(audio_stream);
-
- const AudioDecoderConfig& config = audio_stream->audio_decoder_config();
- EXPECT_EQ(kCodecVorbis, config.codec());
- EXPECT_EQ(32, config.bits_per_channel());
- EXPECT_EQ(CHANNEL_LAYOUT_STEREO, config.channel_layout());
- EXPECT_EQ(44100, config.samples_per_second());
- EXPECT_GT(config.extra_data().size(), 0u);
- EXPECT_EQ(kSampleFormatPlanarF32, config.sample_format());
- EXPECT_EQ(is_audio_encrypted,
- audio_stream->audio_decoder_config().is_encrypted());
- EXPECT_TRUE(static_cast<ChunkDemuxerStream*>(audio_stream)
- ->supports_partial_append_window_trimming());
- } else {
- EXPECT_FALSE(audio_stream);
- }
-
- DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
- if (has_video) {
- EXPECT_TRUE(video_stream);
- EXPECT_EQ(is_video_encrypted,
- video_stream->video_decoder_config().is_encrypted());
- EXPECT_FALSE(static_cast<ChunkDemuxerStream*>(video_stream)
- ->supports_partial_append_window_trimming());
- } else {
- EXPECT_FALSE(video_stream);
- }
-
- ShutdownDemuxer();
- demuxer_.reset();
- }
-}
-
-TEST_P(ChunkDemuxerTest, SingleTextTrackIdChange) {
- // Test with 1 video stream, 1 audio, and 1 text stream. Send a second init
- // segment in which the text track ID changes. Verify appended buffers before
- // and after the second init segment map to the same underlying track buffers.
- CreateNewDemuxer();
- DemuxerStream* text_stream = NULL;
- TextTrackConfig text_config;
- EXPECT_CALL(host_, AddTextStream(_, _))
- .WillOnce(DoAll(SaveArg<0>(&text_stream),
- SaveArg<1>(&text_config)));
- ASSERT_TRUE(InitDemuxerWithEncryptionInfo(
- HAS_TEXT | HAS_AUDIO | HAS_VIDEO, false, false));
- DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
- DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
- ASSERT_TRUE(audio_stream);
- ASSERT_TRUE(video_stream);
- ASSERT_TRUE(text_stream);
-
- AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "0K 23K", 23),
- MuxedStreamInfo(kVideoTrackNum, "0K 30", 30),
- MuxedStreamInfo(kTextTrackNum, "10K"));
- CheckExpectedRanges("{ [0,46) }");
-
- std::unique_ptr<uint8_t[]> info_tracks;
- int info_tracks_size = 0;
- CreateInitSegment(
- HAS_TEXT | HAS_AUDIO | HAS_VIDEO | USE_ALTERNATE_TEXT_TRACK_ID, false,
- false, &info_tracks, &info_tracks_size);
- EXPECT_CALL(*this, InitSegmentReceivedMock(_));
- ASSERT_TRUE(demuxer_->AppendData(
- kSourceId, info_tracks.get(), info_tracks_size,
- append_window_start_for_next_append_, append_window_end_for_next_append_,
- &timestamp_offset_map_[kSourceId]));
-
- AppendMuxedCluster(
- MuxedStreamInfo(kAudioTrackNum, "46K 69K", 23),
- MuxedStreamInfo(kVideoTrackNum, "60K",
- WebMClusterParser::kDefaultVideoBufferDurationInMs),
- MuxedStreamInfo(kAlternateTextTrackNum, "45K"));
-
- CheckExpectedRanges("{ [0,92) }");
- CheckExpectedBuffers(audio_stream, "0K 23K 46K 69K");
- CheckExpectedBuffers(video_stream, "0K 30 60K");
- CheckExpectedBuffers(text_stream, "10K 45K");
-
- ShutdownDemuxer();
-}
-
TEST_P(ChunkDemuxerTest, AudioVideoTrackIdsChange) {
// Test with 1 audio and 1 video stream. Send a second init segment in which
// the audio and video track IDs change. Verify that appended buffers before
@@ -1582,39 +1423,32 @@ TEST_P(ChunkDemuxerTest, InitSegmentSetsNeedRandomAccessPointFlag) {
// to fully test this since needs random access point flag initializes to
// true.
CreateNewDemuxer();
- DemuxerStream* text_stream = NULL;
- EXPECT_CALL(host_, AddTextStream(_, _))
- .WillOnce(SaveArg<0>(&text_stream));
- ASSERT_TRUE(InitDemuxerWithEncryptionInfo(
- HAS_TEXT | HAS_AUDIO | HAS_VIDEO, false, false));
+ ASSERT_TRUE(
+ InitDemuxerWithEncryptionInfo(HAS_AUDIO | HAS_VIDEO, false, false));
DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
- ASSERT_TRUE(audio_stream && video_stream && text_stream);
+ ASSERT_TRUE(audio_stream && video_stream);
AppendMuxedCluster(
MuxedStreamInfo(kAudioTrackNum, "23K",
WebMClusterParser::kDefaultAudioBufferDurationInMs),
- MuxedStreamInfo(kVideoTrackNum, "0 30K", 30),
- MuxedStreamInfo(kTextTrackNum, "25K 40K"));
+ MuxedStreamInfo(kVideoTrackNum, "0 30K", 30));
CheckExpectedRanges("{ [23,46) }");
EXPECT_CALL(*this, InitSegmentReceivedMock(_));
- ASSERT_TRUE(AppendInitSegment(HAS_TEXT | HAS_AUDIO | HAS_VIDEO));
+ ASSERT_TRUE(AppendInitSegment(HAS_AUDIO | HAS_VIDEO));
AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "46K 69K", 23),
- MuxedStreamInfo(kVideoTrackNum, "60 90K", 30),
- MuxedStreamInfo(kTextTrackNum, "80K 90K"));
+ MuxedStreamInfo(kVideoTrackNum, "60 90K", 30));
CheckExpectedRanges("{ [23,92) }");
CheckExpectedBuffers(audio_stream, "23K 46K 69K");
CheckExpectedBuffers(video_stream, "30K 90K");
- CheckExpectedBuffers(text_stream, "25K 40K 80K 90K");
}
TEST_P(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppended) {
EXPECT_CALL(*this, DemuxerOpened());
demuxer_->Initialize(&host_, base::Bind(&ChunkDemuxerTest::DemuxerInitialized,
- base::Unretained(this)),
- true);
+ base::Unretained(this)));
EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
EXPECT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk);
@@ -1626,54 +1460,27 @@ TEST_P(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppended) {
ShutdownDemuxer();
}
-TEST_P(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppendedText) {
- EXPECT_CALL(*this, DemuxerOpened());
- demuxer_->Initialize(&host_, base::Bind(&ChunkDemuxerTest::DemuxerInitialized,
- base::Unretained(this)),
- true);
-
- EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
- EXPECT_EQ(AddId("video_and_text", HAS_VIDEO), ChunkDemuxer::kOk);
-
- EXPECT_CALL(host_, AddTextStream(_, _))
- .Times(Exactly(1));
-
- ExpectInitMediaLogs(HAS_VIDEO);
- EXPECT_CALL(*this, InitSegmentReceivedMock(_));
- ASSERT_TRUE(
- AppendInitSegmentWithSourceId("video_and_text", HAS_VIDEO | HAS_TEXT));
-
- ShutdownDemuxer();
-}
-
// Verifies that all streams waiting for data receive an end of stream
// buffer when Shutdown() is called.
TEST_P(ChunkDemuxerTest, Shutdown_EndOfStreamWhileWaitingForData) {
- DemuxerStream* text_stream = NULL;
- EXPECT_CALL(host_, AddTextStream(_, _))
- .WillOnce(SaveArg<0>(&text_stream));
- ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
+ ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
bool audio_read_done = false;
bool video_read_done = false;
- bool text_read_done = false;
audio_stream->Read(base::Bind(&OnReadDone_EOSExpected, &audio_read_done));
video_stream->Read(base::Bind(&OnReadDone_EOSExpected, &video_read_done));
- text_stream->Read(base::Bind(&OnReadDone_EOSExpected, &text_read_done));
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(audio_read_done);
EXPECT_FALSE(video_read_done);
- EXPECT_FALSE(text_read_done);
ShutdownDemuxer();
EXPECT_TRUE(audio_read_done);
EXPECT_TRUE(video_read_done);
- EXPECT_TRUE(text_read_done);
}
// Test that Seek() completes successfully when the first cluster
@@ -1887,8 +1694,8 @@ TEST_P(ChunkDemuxerTest, PerStreamMonotonicallyIncreasingTimestamps) {
// INFO & TRACKS data.
TEST_P(ChunkDemuxerTest, ClusterBeforeInitSegment) {
EXPECT_CALL(*this, DemuxerOpened());
- demuxer_->Initialize(
- &host_, NewExpectedStatusCB(CHUNK_DEMUXER_ERROR_APPEND_FAILED), true);
+ demuxer_->Initialize(&host_,
+ NewExpectedStatusCB(CHUNK_DEMUXER_ERROR_APPEND_FAILED));
ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
@@ -1900,15 +1707,15 @@ TEST_P(ChunkDemuxerTest, ClusterBeforeInitSegment) {
// Test cases where we get an MarkEndOfStream() call during initialization.
TEST_P(ChunkDemuxerTest, EOSDuringInit) {
EXPECT_CALL(*this, DemuxerOpened());
- demuxer_->Initialize(
- &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
+ demuxer_->Initialize(&host_,
+ NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
MarkEndOfStream(PIPELINE_OK);
}
TEST_P(ChunkDemuxerTest, EndOfStreamWithNoAppend) {
EXPECT_CALL(*this, DemuxerOpened());
- demuxer_->Initialize(
- &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
+ demuxer_->Initialize(&host_,
+ NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
@@ -2108,50 +1915,24 @@ TEST_P(ChunkDemuxerTest, EndOfStreamDuringCanceledSeek) {
// Verify buffered range change behavior for audio/video/text tracks.
TEST_P(ChunkDemuxerTest, EndOfStreamRangeChanges) {
- DemuxerStream* text_stream = NULL;
-
- EXPECT_CALL(host_, AddTextStream(_, _))
- .WillOnce(SaveArg<0>(&text_stream));
- ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
+ ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
AppendMuxedCluster(MuxedStreamInfo(kVideoTrackNum, "0K 33", 33),
MuxedStreamInfo(kAudioTrackNum, "0K 23K", 23));
- // Check expected ranges and verify that an empty text track does not
- // affect the expected ranges.
CheckExpectedRanges("{ [0,46) }");
EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(66)));
MarkEndOfStream(PIPELINE_OK);
- // Check expected ranges and verify that an empty text track does not
- // affect the expected ranges.
CheckExpectedRanges("{ [0,66) }");
-
- // Unmark end of stream state and verify that the ranges return to
- // their pre-"end of stream" values.
- demuxer_->UnmarkEndOfStream();
- CheckExpectedRanges("{ [0,46) }");
-
- // Add text track data and verify that the buffered ranges don't change
- // since the intersection of all the tracks doesn't change.
- EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(200)));
- AppendMuxedCluster(MuxedStreamInfo(kVideoTrackNum, "0K 33", 33),
- MuxedStreamInfo(kAudioTrackNum, "0K 23K", 23),
- MuxedStreamInfo(kTextTrackNum, "0K 100K"));
- CheckExpectedRanges("{ [0,46) }");
-
- // Mark end of stream and verify that text track data is reflected in
- // the new range.
- MarkEndOfStream(PIPELINE_OK);
- CheckExpectedRanges("{ [0,200) }");
}
// Make sure AppendData() will accept elements that span multiple calls.
TEST_P(ChunkDemuxerTest, AppendingInPieces) {
EXPECT_CALL(*this, DemuxerOpened());
- demuxer_->Initialize(
- &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
+ demuxer_->Initialize(&host_,
+ CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
@@ -2199,7 +1980,7 @@ TEST_P(ChunkDemuxerTest, WebMFile_AudioAndVideo) {
// Expect duration adjustment since actual duration differs slightly from
// duration in the init segment.
- EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2746)));
+ EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2768)));
ASSERT_TRUE(ParseWebMFile("bear-320x240.webm", buffer_timestamps,
base::TimeDelta::FromMilliseconds(2744)));
@@ -2243,7 +2024,7 @@ TEST_P(ChunkDemuxerTest, WebMFile_AudioOnly) {
// Expect duration adjustment since actual duration differs slightly from
// duration in the init segment.
- EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2746)));
+ EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2768)));
ASSERT_TRUE(ParseWebMFile("bear-320x240-audio-only.webm", buffer_timestamps,
base::TimeDelta::FromMilliseconds(2744),
@@ -2283,6 +2064,10 @@ TEST_P(ChunkDemuxerTest, WebMFile_AltRefFrames) {
{kSkip, kSkip},
};
+ // Expect duration adjustment since actual duration differs slightly from
+ // duration in the init segment.
+ EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(2768)));
+
ExpectInitMediaLogs(HAS_AUDIO | HAS_VIDEO);
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(2));
ASSERT_TRUE(ParseWebMFile("bear-320x240-altref.webm", buffer_timestamps,
@@ -2345,8 +2130,8 @@ TEST_P(ChunkDemuxerTest, IncrementalClusterParsing) {
TEST_P(ChunkDemuxerTest, ParseErrorDuringInit) {
EXPECT_CALL(*this, DemuxerOpened());
demuxer_->Initialize(
- &host_, CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED),
- true);
+ &host_,
+ CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED));
ASSERT_EQ(AddId(), ChunkDemuxer::kOk);
@@ -2360,8 +2145,8 @@ TEST_P(ChunkDemuxerTest, ParseErrorDuringInit) {
TEST_P(ChunkDemuxerTest, AVHeadersWithAudioOnlyType) {
EXPECT_CALL(*this, DemuxerOpened());
demuxer_->Initialize(
- &host_, CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED),
- true);
+ &host_,
+ CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED));
ASSERT_EQ(AddId(kSourceId, "audio/webm", "vorbis"), ChunkDemuxer::kOk);
@@ -2374,8 +2159,8 @@ TEST_P(ChunkDemuxerTest, AVHeadersWithAudioOnlyType) {
TEST_P(ChunkDemuxerTest, AVHeadersWithVideoOnlyType) {
EXPECT_CALL(*this, DemuxerOpened());
demuxer_->Initialize(
- &host_, CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED),
- true);
+ &host_,
+ CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED));
ASSERT_EQ(AddId(kSourceId, "video/webm", "vp8"), ChunkDemuxer::kOk);
@@ -2390,8 +2175,8 @@ TEST_P(ChunkDemuxerTest, AVHeadersWithVideoOnlyType) {
TEST_P(ChunkDemuxerTest, AudioOnlyHeaderWithAVType) {
EXPECT_CALL(*this, DemuxerOpened());
demuxer_->Initialize(
- &host_, CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED),
- true);
+ &host_,
+ CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED));
ASSERT_EQ(AddId(kSourceId, "video/webm", "vorbis,vp8"), ChunkDemuxer::kOk);
@@ -2406,8 +2191,8 @@ TEST_P(ChunkDemuxerTest, AudioOnlyHeaderWithAVType) {
TEST_P(ChunkDemuxerTest, VideoOnlyHeaderWithAVType) {
EXPECT_CALL(*this, DemuxerOpened());
demuxer_->Initialize(
- &host_, CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED),
- true);
+ &host_,
+ CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED));
ASSERT_EQ(AddId(kSourceId, "video/webm", "vorbis,vp8"), ChunkDemuxer::kOk);
@@ -2450,15 +2235,10 @@ TEST_P(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideo) {
}
TEST_P(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideoText) {
- // TODO(matthewjheaney): Here and elsewhere, we need more tests
- // for inband text tracks (http://crbug/321455).
-
std::string audio_id = "audio1";
std::string video_id = "video1";
- EXPECT_CALL(host_, AddTextStream(_, _))
- .Times(Exactly(2));
- ASSERT_TRUE(InitDemuxerAudioAndVideoSourcesText(audio_id, video_id, true));
+ ASSERT_TRUE(InitDemuxerAudioAndVideoSourcesText(audio_id, video_id));
// Append audio and video data into separate source ids.
ASSERT_TRUE(AppendCluster(
@@ -2473,8 +2253,8 @@ TEST_P(ChunkDemuxerTest, AddSeparateSourcesForAudioAndVideoText) {
TEST_P(ChunkDemuxerTest, AddIdFailures) {
EXPECT_CALL(*this, DemuxerOpened());
- demuxer_->Initialize(
- &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
+ demuxer_->Initialize(&host_,
+ CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
std::string audio_id = "audio1";
std::string video_id = "video1";
@@ -2527,10 +2307,8 @@ TEST_P(ChunkDemuxerTest, RemoveId) {
// quota for new IDs in the future.
TEST_P(ChunkDemuxerTest, RemoveAndAddId) {
demuxer_->Initialize(
- &host_,
- base::BindRepeating(&ChunkDemuxerTest::DemuxerInitialized,
- base::Unretained(this)),
- true);
+ &host_, base::BindRepeating(&ChunkDemuxerTest::DemuxerInitialized,
+ base::Unretained(this)));
std::string audio_id_1 = "audio1";
ASSERT_TRUE(AddId(audio_id_1, HAS_AUDIO) == ChunkDemuxer::kOk);
@@ -2940,32 +2718,6 @@ TEST_P(ChunkDemuxerTest, GetBufferedRanges_AudioVideo) {
CheckExpectedRanges("{ [0,23) [300,400) [600,670) [900,950) [1200,1250) }");
}
-TEST_P(ChunkDemuxerTest, GetBufferedRanges_AudioVideoText) {
- EXPECT_CALL(host_, AddTextStream(_, _));
- ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
-
- // Append audio & video data
- AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "0K 23K", 23),
- MuxedStreamInfo(kVideoTrackNum, "0K 33", 33));
-
- // Verify that a text track with no cues does not result in an empty buffered
- // range.
- CheckExpectedRanges("{ [0,46) }");
-
- // Add some text cues.
- AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "100K 123K", 23),
- MuxedStreamInfo(kVideoTrackNum, "100K 133", 33),
- MuxedStreamInfo(kTextTrackNum, "100K 200K"));
-
- // Verify that the text cues are not reflected in the buffered ranges.
- CheckExpectedRanges("{ [0,46) [100,146) }");
-
- // Remove the buffered ranges.
- demuxer_->Remove(kSourceId, base::TimeDelta(),
- base::TimeDelta::FromMilliseconds(250));
- CheckExpectedRanges("{ }");
-}
-
// Once MarkEndOfStream() is called, GetBufferedRanges should not cut off any
// over-hanging tails at the end of the ranges as this is likely due to block
// duration differences.
@@ -3092,10 +2844,8 @@ TEST_P(ChunkDemuxerTest, DifferentStreamTimecodesOutOfRange) {
TEST_P(ChunkDemuxerTest, CodecPrefixMatching) {
demuxer_->Initialize(
- &host_,
- base::BindRepeating(&ChunkDemuxerTest::DemuxerInitialized,
- base::Unretained(this)),
- true);
+ &host_, base::BindRepeating(&ChunkDemuxerTest::DemuxerInitialized,
+ base::Unretained(this)));
ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported;
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
@@ -3126,10 +2876,8 @@ TEST_P(ChunkDemuxerTest, CodecIDsThatAreNotRFC6381Compliant) {
};
demuxer_->Initialize(
- &host_,
- base::BindRepeating(&ChunkDemuxerTest::DemuxerInitialized,
- base::Unretained(this)),
- true);
+ &host_, base::BindRepeating(&ChunkDemuxerTest::DemuxerInitialized,
+ base::Unretained(this)));
for (size_t i = 0; i < arraysize(codec_ids); ++i) {
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
@@ -3188,8 +2936,7 @@ TEST_P(ChunkDemuxerTest, EndOfStreamStillSetAfterSeek) {
TEST_P(ChunkDemuxerTest, GetBufferedRangesBeforeInitSegment) {
EXPECT_CALL(*this, DemuxerOpened());
demuxer_->Initialize(&host_, base::Bind(&ChunkDemuxerTest::DemuxerInitialized,
- base::Unretained(this)),
- true);
+ base::Unretained(this)));
ASSERT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
ASSERT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk);
@@ -3453,8 +3200,8 @@ TEST_P(ChunkDemuxerTest, EmitBuffersDuringAbort) {
EXPECT_MEDIA_LOG(CodecName("audio", "aac"));
EXPECT_MEDIA_LOG(FoundStream("video"));
EXPECT_MEDIA_LOG(CodecName("video", "h264"));
- demuxer_->Initialize(&host_, CreateInitDoneCB(kInfiniteDuration, PIPELINE_OK),
- true);
+ demuxer_->Initialize(&host_,
+ CreateInitDoneCB(kInfiniteDuration, PIPELINE_OK));
EXPECT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, kMp2tMimeType, kMp2tCodecs));
// For info:
@@ -3523,8 +3270,8 @@ TEST_P(ChunkDemuxerTest, SeekCompleteDuringAbort) {
EXPECT_MEDIA_LOG(CodecName("audio", "aac"));
EXPECT_MEDIA_LOG(FoundStream("video"));
EXPECT_MEDIA_LOG(CodecName("video", "h264"));
- demuxer_->Initialize(&host_, CreateInitDoneCB(kInfiniteDuration, PIPELINE_OK),
- true);
+ demuxer_->Initialize(&host_,
+ CreateInitDoneCB(kInfiniteDuration, PIPELINE_OK));
EXPECT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, kMp2tMimeType, kMp2tCodecs));
// For info:
@@ -3655,7 +3402,6 @@ TEST_P(ChunkDemuxerTest, WebMIsParsingMediaSegmentDetection) {
ASSERT_TRUE(InitDemuxer(HAS_AUDIO));
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(23)).Times(2);
- EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(2000, 1000, 22000));
for (size_t i = 0; i < sizeof(kBuffer); i++) {
DVLOG(3) << "Appending and testing index " << i;
ASSERT_TRUE(AppendData(kBuffer + i, 1));
@@ -3745,8 +3491,7 @@ TEST_P(ChunkDemuxerTest, AppendAfterEndOfStream) {
// the pipeline has a chance to initialize the demuxer.
TEST_P(ChunkDemuxerTest, Shutdown_BeforeInitialize) {
demuxer_->Shutdown();
- demuxer_->Initialize(
- &host_, CreateInitDoneCB(DEMUXER_ERROR_COULD_NOT_OPEN), true);
+ demuxer_->Initialize(&host_, CreateInitDoneCB(DEMUXER_ERROR_COULD_NOT_OPEN));
base::RunLoop().RunUntilIdle();
}
@@ -4184,8 +3929,7 @@ TEST_P(ChunkDemuxerTest, AppendWindow_WebMFile_AudioOnly) {
EXPECT_CALL(*this, DemuxerOpened());
demuxer_->Initialize(
&host_,
- CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744), PIPELINE_OK),
- true);
+ CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744), PIPELINE_OK));
ASSERT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, HAS_AUDIO));
// Set the append window to [50,150).
@@ -4218,15 +3962,14 @@ TEST_P(ChunkDemuxerTest, AppendWindow_AudioConfigUpdateRemovesPreroll) {
EXPECT_CALL(*this, DemuxerOpened());
demuxer_->Initialize(
&host_,
- CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744), PIPELINE_OK),
- true);
+ CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744), PIPELINE_OK));
ASSERT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, HAS_AUDIO));
// Set the append window such that the first file is completely before the
// append window.
// Expect duration adjustment since actual duration differs slightly from
// duration in the init segment.
- const base::TimeDelta duration_1 = base::TimeDelta::FromMilliseconds(2746);
+ const base::TimeDelta duration_1 = base::TimeDelta::FromMilliseconds(2768);
append_window_start_for_next_append_ = duration_1;
EXPECT_MEDIA_LOG(DroppedFrameCheckAppendWindow(
@@ -4251,69 +3994,16 @@ TEST_P(ChunkDemuxerTest, AppendWindow_AudioConfigUpdateRemovesPreroll) {
scoped_refptr<DecoderBuffer> buffer2 =
ReadTestDataFile("bear-320x240-audio-only-48khz.webm");
EXPECT_CALL(*this, InitSegmentReceivedMock(_));
- EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(21));
+ EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(22));
EXPECT_CALL(host_, SetDuration(_)).Times(AnyNumber());
ASSERT_TRUE(SetTimestampOffset(kSourceId, duration_1));
ASSERT_TRUE(AppendDataInPieces(buffer2->data(), buffer2->data_size(), 512));
- CheckExpectedRanges("{ [2746,5519) }");
+ CheckExpectedRanges("{ [2768,5542) }");
Seek(duration_1);
ExpectConfigChanged(DemuxerStream::AUDIO);
ASSERT_FALSE(config_1.Matches(stream->audio_decoder_config()));
- CheckExpectedBuffers(stream, "2746K 2767K 2789K 2810K");
-}
-
-TEST_P(ChunkDemuxerTest, AppendWindow_Text) {
- DemuxerStream* text_stream = NULL;
- EXPECT_CALL(host_, AddTextStream(_, _))
- .WillOnce(SaveArg<0>(&text_stream));
- ASSERT_TRUE(InitDemuxer(HAS_VIDEO | HAS_TEXT));
- DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
-
- // Set the append window to [20,280).
- append_window_start_for_next_append_ = base::TimeDelta::FromMilliseconds(20);
- append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(280);
-
- EXPECT_MEDIA_LOG(DroppedFrame("video", 0));
- EXPECT_MEDIA_LOG(DroppedFrame("text", 0));
- EXPECT_MEDIA_LOG(DroppedFrame("text", 200000));
- EXPECT_MEDIA_LOG(DroppedFrame("video", 270000));
- EXPECT_MEDIA_LOG(DroppedFrame("video", 300000));
- EXPECT_MEDIA_LOG(DroppedFrame("text", 300000));
- EXPECT_MEDIA_LOG(DroppedFrame("video", 330000));
-
- // Append a cluster that starts before and ends after the append
- // window.
- AppendMuxedCluster(
- MuxedStreamInfo(kVideoTrackNum,
- "0K 30 60 90 120K 150 180 210 240K 270 300 330K", 30),
- MuxedStreamInfo(kTextTrackNum, "0K 100K 200K 300K"));
-
- // Verify that text cues that start outside the window are not included
- // in the buffer. Also verify that cues that extend beyond the
- // window are not included.
- CheckExpectedRanges("{ [100,270) }");
- CheckExpectedBuffers(video_stream, "120K 150 180 210 240K");
- CheckExpectedBuffers(text_stream, "100K");
-
- // Extend the append window to [20,650).
- append_window_end_for_next_append_ = base::TimeDelta::FromMilliseconds(650);
-
- EXPECT_MEDIA_LOG(DroppedFrame("text", 600000));
- EXPECT_MEDIA_LOG(DroppedFrame("video", 630000));
- EXPECT_MEDIA_LOG(DroppedFrame("text", 700000));
-
- // Append more data and verify that a new range is created.
- AppendMuxedCluster(
- MuxedStreamInfo(kVideoTrackNum,
- "360 390 420K 450 480 510 540K 570 600 630K", 30),
- MuxedStreamInfo(kTextTrackNum, "400K 500K 600K 700K"));
- CheckExpectedRanges("{ [100,270) [400,630) }");
-
- // Seek to the new range and verify that the expected buffers are returned.
- Seek(base::TimeDelta::FromMilliseconds(420));
- CheckExpectedBuffers(video_stream, "420K 450 480 510 540K 570 600");
- CheckExpectedBuffers(text_stream, "400K 500K");
+ CheckExpectedBuffers(stream, "2768K 2789K 2811K 2832K");
}
TEST_P(ChunkDemuxerTest, StartWaitingForSeekAfterParseError) {
@@ -4326,22 +4016,17 @@ TEST_P(ChunkDemuxerTest, StartWaitingForSeekAfterParseError) {
}
TEST_P(ChunkDemuxerTest, Remove_AudioVideoText) {
- DemuxerStream* text_stream = NULL;
- EXPECT_CALL(host_, AddTextStream(_, _))
- .WillOnce(SaveArg<0>(&text_stream));
- ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
+ ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
AppendMuxedCluster(
MuxedStreamInfo(kAudioTrackNum, "0K 20K 40K 60K 80K 100K 120K 140K", 20),
- MuxedStreamInfo(kVideoTrackNum, "0K 30 60 90 120K 150 180", 30),
- MuxedStreamInfo(kTextTrackNum, "0K 100K 200K"));
+ MuxedStreamInfo(kVideoTrackNum, "0K 30 60 90 120K 150 180", 30));
CheckExpectedBuffers(audio_stream, "0K 20K 40K 60K 80K 100K 120K 140K");
CheckExpectedBuffers(video_stream, "0K 30 60 90 120K 150 180");
- CheckExpectedBuffers(text_stream, "0K 100K 200K");
// Remove the buffers that were added.
demuxer_->Remove(kSourceId, base::TimeDelta(),
@@ -4354,13 +4039,11 @@ TEST_P(ChunkDemuxerTest, Remove_AudioVideoText) {
// ones and verify that only the new buffers are returned.
AppendMuxedCluster(
MuxedStreamInfo(kAudioTrackNum, "1K 21K 41K 61K 81K 101K 121K 141K", 20),
- MuxedStreamInfo(kVideoTrackNum, "1K 31 61 91 121K 151 181", 30),
- MuxedStreamInfo(kTextTrackNum, "1K 101K 201K"));
+ MuxedStreamInfo(kVideoTrackNum, "1K 31 61 91 121K 151 181", 30));
Seek(base::TimeDelta());
CheckExpectedBuffers(audio_stream, "1K 21K 41K 61K 81K 101K 121K 141K");
CheckExpectedBuffers(video_stream, "1K 31 61 91 121K 151 181");
- CheckExpectedBuffers(text_stream, "1K 101K 201K");
}
TEST_P(ChunkDemuxerTest, Remove_StartAtDuration) {
@@ -4394,10 +4077,7 @@ TEST_P(ChunkDemuxerTest, Remove_StartAtDuration) {
// the seek point and will return cues after the seek position
// when they are eventually appended.
TEST_P(ChunkDemuxerTest, SeekCompletesWithoutTextCues) {
- DemuxerStream* text_stream = NULL;
- EXPECT_CALL(host_, AddTextStream(_, _))
- .WillOnce(SaveArg<0>(&text_stream));
- ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO | HAS_TEXT));
+ ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO));
DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO);
DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
@@ -4411,11 +4091,6 @@ TEST_P(ChunkDemuxerTest, SeekCompletesWithoutTextCues) {
EXPECT_FALSE(seek_cb_was_called);
- bool text_read_done = false;
- text_stream->Read(base::Bind(&OnReadDone,
- base::TimeDelta::FromMilliseconds(225),
- &text_read_done));
-
// Append audio & video data so the seek completes.
AppendMuxedCluster(
MuxedStreamInfo(kAudioTrackNum,
@@ -4424,26 +4099,17 @@ TEST_P(ChunkDemuxerTest, SeekCompletesWithoutTextCues) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(seek_cb_was_called);
- EXPECT_FALSE(text_read_done);
// Read some audio & video buffers to further verify seek completion.
CheckExpectedBuffers(audio_stream, "120K 140K");
CheckExpectedBuffers(video_stream, "120K 150");
- EXPECT_FALSE(text_read_done);
-
// Append text cues that start after the seek point and verify that
// they are returned by Read() calls.
AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "220K 240K 260K 280K", 20),
- MuxedStreamInfo(kVideoTrackNum, "240K 270 300 330", 30),
- MuxedStreamInfo(kTextTrackNum, "225K 275K 325K"));
+ MuxedStreamInfo(kVideoTrackNum, "240K 270 300 330", 30));
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(text_read_done);
-
- // NOTE: we start at 275 here because the buffer at 225 was returned
- // to the pending read initiated above.
- CheckExpectedBuffers(text_stream, "275K 325K");
// Verify that audio & video streams continue to return expected values.
CheckExpectedBuffers(audio_stream, "160K 180K");
@@ -4845,8 +4511,7 @@ TEST_P(ChunkDemuxerTest, MultipleIds) {
CreateNewDemuxer();
EXPECT_CALL(*this, DemuxerOpened());
EXPECT_CALL(host_, SetDuration(_)).Times(2);
- demuxer_->Initialize(&host_, CreateInitDoneCB(kNoTimestamp, PIPELINE_OK),
- true);
+ demuxer_->Initialize(&host_, CreateInitDoneCB(kNoTimestamp, PIPELINE_OK));
const char* kId1 = "id1";
const char* kId2 = "id2";
@@ -4872,7 +4537,7 @@ TEST_P(ChunkDemuxerTest, CompleteInitAfterIdRemoved) {
CreateNewDemuxer();
EXPECT_CALL(*this, DemuxerOpened());
demuxer_->Initialize(&host_,
- CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
+ CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
// Add two ids, then remove one of the ids and verify that adding init segment
// only for the remaining id still triggers the InitDoneCB.
@@ -4895,7 +4560,7 @@ TEST_P(ChunkDemuxerTest, RemovingIdMustRemoveStreams) {
CreateNewDemuxer();
EXPECT_CALL(*this, DemuxerOpened());
demuxer_->Initialize(&host_,
- CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
+ CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK));
const char* kId1 = "id1";
EXPECT_EQ(AddId(kId1, "video/webm", "vorbis,vp8"), ChunkDemuxer::kOk);
@@ -4952,10 +4617,8 @@ TEST_P(ChunkDemuxerTest, SequenceModeSingleTrackNoWarning) {
TEST_P(ChunkDemuxerTest, Mp4Vp9CodecSupport) {
demuxer_->Initialize(
- &host_,
- base::BindRepeating(&ChunkDemuxerTest::DemuxerInitialized,
- base::Unretained(this)),
- true);
+ &host_, base::BindRepeating(&ChunkDemuxerTest::DemuxerInitialized,
+ base::Unretained(this)));
ChunkDemuxer::Status expected = ChunkDemuxer::kOk;
EXPECT_EQ(AddId("source_id", "video/mp4", "vp09.00.10.08"), expected);
}
@@ -4966,8 +4629,8 @@ TEST_P(ChunkDemuxerTest, UnmarkEOSRetainsParseErrorState_BeforeInit) {
EXPECT_CALL(*this, DemuxerOpened());
EXPECT_MEDIA_LOG(StreamParsingFailed());
demuxer_->Initialize(
- &host_, CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED),
- true);
+ &host_,
+ CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED));
ASSERT_EQ(AddId(kSourceId, HAS_AUDIO | HAS_VIDEO), ChunkDemuxer::kOk);
AppendGarbage();
diff --git a/chromium/media/filters/decoder_stream.cc b/chromium/media/filters/decoder_stream.cc
index c4ecd423fbc..09d61733315 100644
--- a/chromium/media/filters/decoder_stream.cc
+++ b/chromium/media/filters/decoder_stream.cc
@@ -73,13 +73,13 @@ DecoderStream<StreamType>::~DecoderStream() {
DCHECK(task_runner_->BelongsToCurrentThread());
if (init_cb_) {
- task_runner_->PostTask(
- FROM_HERE, base::BindOnce(base::ResetAndReturn(&init_cb_), false));
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(std::move(init_cb_), false));
}
if (read_cb_) {
task_runner_->PostTask(
- FROM_HERE, base::BindOnce(base::ResetAndReturn(&read_cb_), ABORTED,
- scoped_refptr<Output>()));
+ FROM_HERE,
+ base::BindOnce(std::move(read_cb_), ABORTED, scoped_refptr<Output>()));
}
if (reset_cb_)
task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_));
@@ -96,10 +96,10 @@ std::string DecoderStream<StreamType>::GetStreamTypeString() {
template <DemuxerStream::Type StreamType>
void DecoderStream<StreamType>::Initialize(
DemuxerStream* stream,
- const InitCB& init_cb,
+ InitCB init_cb,
CdmContext* cdm_context,
- const StatisticsCB& statistics_cb,
- const base::Closure& waiting_for_decryption_key_cb) {
+ StatisticsCB statistics_cb,
+ base::RepeatingClosure waiting_for_decryption_key_cb) {
FUNCTION_DVLOG(1);
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, STATE_UNINITIALIZED);
@@ -107,10 +107,10 @@ void DecoderStream<StreamType>::Initialize(
DCHECK(init_cb);
stream_ = stream;
- init_cb_ = init_cb;
+ init_cb_ = std::move(init_cb);
cdm_context_ = cdm_context;
- statistics_cb_ = statistics_cb;
- waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb;
+ statistics_cb_ = std::move(statistics_cb);
+ waiting_for_decryption_key_cb_ = std::move(waiting_for_decryption_key_cb);
traits_->OnStreamReset(stream_);
@@ -119,7 +119,7 @@ void DecoderStream<StreamType>::Initialize(
}
template <DemuxerStream::Type StreamType>
-void DecoderStream<StreamType>::Read(const ReadCB& read_cb) {
+void DecoderStream<StreamType>::Read(ReadCB read_cb) {
FUNCTION_DVLOG(3);
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_INITIALIZING)
@@ -130,26 +130,27 @@ void DecoderStream<StreamType>::Read(const ReadCB& read_cb) {
DCHECK(!reset_cb_);
if (state_ == STATE_ERROR) {
- task_runner_->PostTask(FROM_HERE, base::BindOnce(read_cb, DECODE_ERROR,
- scoped_refptr<Output>()));
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(std::move(read_cb), DECODE_ERROR,
+ scoped_refptr<Output>()));
return;
}
if (state_ == STATE_END_OF_STREAM && ready_outputs_.empty() &&
unprepared_outputs_.empty()) {
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(read_cb, OK, StreamTraits::CreateEOSOutput()));
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(std::move(read_cb), OK,
+ StreamTraits::CreateEOSOutput()));
return;
}
if (!ready_outputs_.empty()) {
- task_runner_->PostTask(FROM_HERE,
- base::BindOnce(read_cb, OK, ready_outputs_.front()));
+ task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(read_cb), OK,
+ ready_outputs_.front()));
ready_outputs_.pop_front();
MaybePrepareAnotherOutput();
} else {
- read_cb_ = read_cb;
+ read_cb_ = std::move(read_cb);
}
if (state_ == STATE_NORMAL && CanDecodeMore())
@@ -157,18 +158,18 @@ void DecoderStream<StreamType>::Read(const ReadCB& read_cb) {
}
template <DemuxerStream::Type StreamType>
-void DecoderStream<StreamType>::Reset(const base::Closure& closure) {
+void DecoderStream<StreamType>::Reset(base::OnceClosure closure) {
FUNCTION_DVLOG(2);
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK_NE(state_, STATE_UNINITIALIZED);
DCHECK(!reset_cb_);
- reset_cb_ = closure;
+ reset_cb_ = std::move(closure);
if (read_cb_) {
task_runner_->PostTask(
- FROM_HERE, base::BindOnce(base::ResetAndReturn(&read_cb_), ABORTED,
- scoped_refptr<Output>()));
+ FROM_HERE,
+ base::BindOnce(std::move(read_cb_), ABORTED, scoped_refptr<Output>()));
}
ClearOutputs();
@@ -328,7 +329,7 @@ void DecoderStream<StreamType>::OnDecoderSelected(
state_ = STATE_UNINITIALIZED;
MEDIA_LOG(ERROR, media_log_)
<< GetStreamTypeString() << " decoder initialization failed";
- base::ResetAndReturn(&init_cb_).Run(false);
+ std::move(init_cb_).Run(false);
} else {
CompleteDecoderReinitialization(false);
}
@@ -341,6 +342,9 @@ void DecoderStream<StreamType>::OnDecoderSelected(
!!decrypting_demuxer_stream_);
media_log_->SetStringProperty(GetStreamTypeString() + "_decoder",
decoder_->GetDisplayName());
+ media_log_->SetBooleanProperty(
+ "is_platform_" + GetStreamTypeString() + "_decoder",
+ decoder_->IsPlatformDecoder());
MEDIA_LOG(INFO, media_log_)
<< "Selected " << decoder_->GetDisplayName() << " for "
@@ -356,7 +360,7 @@ void DecoderStream<StreamType>::OnDecoderSelected(
state_ = STATE_NORMAL;
if (StreamTraits::NeedsBitstreamConversion(decoder_.get()))
stream_->EnableBitstreamConverter();
- base::ResetAndReturn(&init_cb_).Run(true);
+ std::move(init_cb_).Run(true);
}
template <DemuxerStream::Type StreamType>
@@ -364,7 +368,7 @@ void DecoderStream<StreamType>::SatisfyRead(
Status status,
const scoped_refptr<Output>& output) {
DCHECK(read_cb_);
- base::ResetAndReturn(&read_cb_).Run(status, output);
+ std::move(read_cb_).Run(status, output);
}
template <DemuxerStream::Type StreamType>
diff --git a/chromium/media/filters/decoder_stream.h b/chromium/media/filters/decoder_stream.h
index 95bd78f81eb..50707c37a26 100644
--- a/chromium/media/filters/decoder_stream.h
+++ b/chromium/media/filters/decoder_stream.h
@@ -56,11 +56,10 @@ class MEDIA_EXPORT DecoderStream {
base::RepeatingCallback<std::vector<std::unique_ptr<Decoder>>()>;
// Indicates completion of a DecoderStream initialization.
- using InitCB = base::RepeatingCallback<void(bool success)>;
+ using InitCB = base::OnceCallback<void(bool success)>;
// Indicates completion of a DecoderStream read.
- using ReadCB =
- base::RepeatingCallback<void(Status, const scoped_refptr<Output>&)>;
+ using ReadCB = base::OnceCallback<void(Status, const scoped_refptr<Output>&)>;
DecoderStream(std::unique_ptr<DecoderStreamTraits<StreamType>> traits,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
@@ -76,16 +75,16 @@ class MEDIA_EXPORT DecoderStream {
// |cdm_context| can be used to handle encrypted stream. Can be null if the
// stream is not encrypted.
void Initialize(DemuxerStream* stream,
- const InitCB& init_cb,
+ InitCB init_cb,
CdmContext* cdm_context,
- const StatisticsCB& statistics_cb,
- const base::Closure& waiting_for_decryption_key_cb);
+ StatisticsCB statistics_cb,
+ base::RepeatingClosure waiting_for_decryption_key_cb);
// Reads a decoded Output and returns it via the |read_cb|. Note that
// |read_cb| is always called asynchronously. This method should only be
// called after initialization has succeeded and must not be called during
// pending Reset().
- void Read(const ReadCB& read_cb);
+ void Read(ReadCB read_cb);
// Resets the decoder, flushes all decoded outputs and/or internal buffers,
// fires any existing pending read callback and calls |closure| on completion.
@@ -94,7 +93,7 @@ class MEDIA_EXPORT DecoderStream {
// during pending Reset().
// N.B: If the decoder stream has run into an error, calling this method does
// not 'reset' it to a normal state.
- void Reset(const base::Closure& closure);
+ void Reset(base::OnceClosure closure);
// Returns true if the decoder currently has the ability to decode and return
// an Output.
@@ -224,10 +223,10 @@ class MEDIA_EXPORT DecoderStream {
StatisticsCB statistics_cb_;
InitCB init_cb_;
- base::Closure waiting_for_decryption_key_cb_;
+ base::RepeatingClosure waiting_for_decryption_key_cb_;
ReadCB read_cb_;
- base::Closure reset_cb_;
+ base::OnceClosure reset_cb_;
DemuxerStream* stream_;
diff --git a/chromium/media/filters/decrypting_audio_decoder.cc b/chromium/media/filters/decrypting_audio_decoder.cc
index e09411ed90e..767b405ef18 100644
--- a/chromium/media/filters/decrypting_audio_decoder.cc
+++ b/chromium/media/filters/decrypting_audio_decoder.cc
@@ -94,7 +94,7 @@ void DecryptingAudioDecoder::Initialize(
if (state_ == kUninitialized) {
if (!cdm_context->GetDecryptor()) {
- MEDIA_LOG(DEBUG, media_log_) << GetDisplayName() << ": no decryptor";
+ DVLOG(1) << __func__ << ": no decryptor";
base::ResetAndReturn(&init_cb_).Run(false);
return;
}
@@ -141,10 +141,9 @@ void DecryptingAudioDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
void DecryptingAudioDecoder::Reset(const base::Closure& closure) {
DVLOG(2) << "Reset() - state: " << state_;
DCHECK(task_runner_->BelongsToCurrentThread());
- DCHECK(state_ == kIdle ||
- state_ == kPendingDecode ||
- state_ == kWaitingForKey ||
- state_ == kDecodeFinished) << state_;
+ DCHECK(state_ == kIdle || state_ == kPendingDecode ||
+ state_ == kWaitingForKey || state_ == kDecodeFinished)
+ << state_;
DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
DCHECK(reset_cb_.is_null());
@@ -194,9 +193,8 @@ DecryptingAudioDecoder::~DecryptingAudioDecoder() {
void DecryptingAudioDecoder::InitializeDecoder() {
state_ = kPendingDecoderInit;
decryptor_->InitializeAudioDecoder(
- config_,
- BindToCurrentLoop(base::Bind(
- &DecryptingAudioDecoder::FinishInitialization, weak_this_)));
+ config_, BindToCurrentLoop(base::Bind(
+ &DecryptingAudioDecoder::FinishInitialization, weak_this_)));
}
void DecryptingAudioDecoder::FinishInitialization(bool success) {
@@ -204,12 +202,11 @@ void DecryptingAudioDecoder::FinishInitialization(bool success) {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(state_ == kPendingDecoderInit) << state_;
DCHECK(!init_cb_.is_null());
- DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
+ DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished.
if (!success) {
- MEDIA_LOG(DEBUG, media_log_) << GetDisplayName()
- << ": failed to init decoder on decryptor";
+ DVLOG(1) << __func__ << ": failed to init audio decoder on decryptor";
base::ResetAndReturn(&init_cb_).Run(false);
decryptor_ = NULL;
state_ = kError;
@@ -221,9 +218,8 @@ void DecryptingAudioDecoder::FinishInitialization(bool success) {
new AudioTimestampHelper(config_.samples_per_second()));
decryptor_->RegisterNewKeyCB(
- Decryptor::kAudio,
- BindToCurrentLoop(
- base::Bind(&DecryptingAudioDecoder::OnKeyAdded, weak_this_)));
+ Decryptor::kAudio, BindToCurrentLoop(base::Bind(
+ &DecryptingAudioDecoder::OnKeyAdded, weak_this_)));
state_ = kIdle;
base::ResetAndReturn(&init_cb_).Run(true);
@@ -240,8 +236,8 @@ void DecryptingAudioDecoder::DecodePendingBuffer() {
decryptor_->DecryptAndDecodeAudio(
pending_buffer_to_decode_,
- BindToCurrentLoop(base::Bind(
- &DecryptingAudioDecoder::DeliverFrame, weak_this_, buffer_size)));
+ BindToCurrentLoop(base::Bind(&DecryptingAudioDecoder::DeliverFrame,
+ weak_this_, buffer_size)));
}
void DecryptingAudioDecoder::DeliverFrame(
@@ -271,7 +267,7 @@ void DecryptingAudioDecoder::DeliverFrame(
if (status == Decryptor::kError) {
DVLOG(2) << "DeliverFrame() - kError";
MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": decode error";
- state_ = kDecodeFinished; // TODO add kError state
+ state_ = kDecodeFinished; // TODO add kError state
base::ResetAndReturn(&decode_cb_).Run(DecodeStatus::DECODE_ERROR);
return;
}
@@ -279,10 +275,11 @@ void DecryptingAudioDecoder::DeliverFrame(
if (status == Decryptor::kNoKey) {
std::string key_id =
scoped_pending_buffer_to_decode->decrypt_config()->key_id();
- std::string missing_key_id = base::HexEncode(key_id.data(), key_id.size());
- DVLOG(1) << "DeliverFrame() - no key for key ID " << missing_key_id;
- MEDIA_LOG(DEBUG, media_log_) << GetDisplayName() << ": no key for key ID "
- << missing_key_id;
+ std::string log_message =
+ "no key for key ID " + base::HexEncode(key_id.data(), key_id.size()) +
+ "; will resume decoding after new usable key is available";
+ DVLOG(1) << __func__ << ": " << log_message;
+ MEDIA_LOG(INFO, media_log_) << GetDisplayName() << ": " << log_message;
// Set |pending_buffer_to_decode_| back as we need to try decoding the
// pending buffer again when new key is added to the decryptor.
@@ -290,8 +287,8 @@ void DecryptingAudioDecoder::DeliverFrame(
if (need_to_try_again_if_nokey_is_returned) {
// The |state_| is still kPendingDecode.
- MEDIA_LOG(INFO, media_log_) << GetDisplayName()
- << ": key was added, resuming decode";
+ MEDIA_LOG(INFO, media_log_)
+ << GetDisplayName() << ": key was added, resuming decode";
DecodePendingBuffer();
return;
}
@@ -334,8 +331,8 @@ void DecryptingAudioDecoder::OnKeyAdded() {
}
if (state_ == kWaitingForKey) {
- MEDIA_LOG(INFO, media_log_) << GetDisplayName()
- << ": key added, resuming decode";
+ MEDIA_LOG(INFO, media_log_)
+ << GetDisplayName() << ": key added, resuming decode";
state_ = kPendingDecode;
DecodePendingBuffer();
}
@@ -352,8 +349,7 @@ void DecryptingAudioDecoder::DoReset() {
void DecryptingAudioDecoder::ProcessDecodedFrames(
const Decryptor::AudioFrames& frames) {
for (Decryptor::AudioFrames::const_iterator iter = frames.begin();
- iter != frames.end();
- ++iter) {
+ iter != frames.end(); ++iter) {
scoped_refptr<AudioBuffer> frame = *iter;
DCHECK(!frame->end_of_stream()) << "EOS frame returned.";
diff --git a/chromium/media/filters/decrypting_audio_decoder_unittest.cc b/chromium/media/filters/decrypting_audio_decoder_unittest.cc
index f68e048aed9..8a5b4621a37 100644
--- a/chromium/media/filters/decrypting_audio_decoder_unittest.cc
+++ b/chromium/media/filters/decrypting_audio_decoder_unittest.cc
@@ -111,16 +111,14 @@ class DecryptingAudioDecoderTest : public testing::Test {
InitializeAndExpectResult(config_, true);
}
- void Reinitialize() {
- ReinitializeConfigChange(config_);
- }
+ void Reinitialize() { ReinitializeConfigChange(config_); }
void ReinitializeConfigChange(const AudioDecoderConfig& new_config) {
EXPECT_CALL(*decryptor_, DeinitializeDecoder(Decryptor::kAudio));
EXPECT_CALL(*decryptor_, InitializeAudioDecoder(_, _))
.WillOnce(RunCallback<1>(true));
EXPECT_CALL(*decryptor_, RegisterNewKeyCB(Decryptor::kAudio, _))
- .WillOnce(SaveArg<1>(&key_added_cb_));
+ .WillOnce(SaveArg<1>(&key_added_cb_));
decoder_->Initialize(
new_config, cdm_context_.get(), NewExpectedBoolCB(true),
base::Bind(&DecryptingAudioDecoderTest::FrameReady,
@@ -133,9 +131,8 @@ class DecryptingAudioDecoderTest : public testing::Test {
void DecodeAndExpect(scoped_refptr<DecoderBuffer> buffer,
DecodeStatus status) {
EXPECT_CALL(*this, DecodeDone(status));
- decoder_->Decode(buffer,
- base::Bind(&DecryptingAudioDecoderTest::DecodeDone,
- base::Unretained(this)));
+ decoder_->Decode(buffer, base::Bind(&DecryptingAudioDecoderTest::DecodeDone,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
}
@@ -161,8 +158,9 @@ class DecryptingAudioDecoderTest : public testing::Test {
// Sets up expectations and actions to put DecryptingAudioDecoder in an
// active normal decoding state.
void EnterNormalDecodingState() {
- EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _)).WillRepeatedly(
- Invoke(this, &DecryptingAudioDecoderTest::DecryptAndDecodeAudio));
+ EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
+ .WillRepeatedly(
+ Invoke(this, &DecryptingAudioDecoderTest::DecryptAndDecodeAudio));
EXPECT_CALL(*this, FrameReady(decoded_frame_));
for (int i = 0; i < kDecodingDelay + 1; ++i)
DecodeAndExpect(encrypted_buffer_, DecodeStatus::OK);
@@ -173,8 +171,7 @@ class DecryptingAudioDecoderTest : public testing::Test {
// EnterNormalDecodingState() to work.
void EnterEndOfStreamState() {
// The codec in the |decryptor_| will be flushed.
- EXPECT_CALL(*this, FrameReady(decoded_frame_))
- .Times(kDecodingDelay);
+ EXPECT_CALL(*this, FrameReady(decoded_frame_)).Times(kDecodingDelay);
DecodeAndExpect(DecoderBuffer::CreateEOSBuffer(), DecodeStatus::OK);
EXPECT_EQ(0, num_frames_in_decryptor_);
}
@@ -196,8 +193,8 @@ class DecryptingAudioDecoderTest : public testing::Test {
void EnterWaitingForKeyState() {
EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(encrypted_buffer_, _))
- .WillRepeatedly(RunCallback<1>(Decryptor::kNoKey,
- Decryptor::AudioFrames()));
+ .WillRepeatedly(
+ RunCallback<1>(Decryptor::kNoKey, Decryptor::AudioFrames()));
EXPECT_CALL(*this, OnWaitingForDecryptionKey());
decoder_->Decode(encrypted_buffer_,
base::Bind(&DecryptingAudioDecoderTest::DecodeDone,
@@ -208,8 +205,8 @@ class DecryptingAudioDecoderTest : public testing::Test {
void AbortPendingAudioDecodeCB() {
if (!pending_audio_decode_cb_.is_null()) {
- base::ResetAndReturn(&pending_audio_decode_cb_).Run(
- Decryptor::kSuccess, Decryptor::AudioFrames());
+ base::ResetAndReturn(&pending_audio_decode_cb_)
+ .Run(Decryptor::kSuccess, Decryptor::AudioFrames());
}
}
@@ -315,8 +312,8 @@ TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_DecodeError) {
Initialize();
EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
- .WillRepeatedly(RunCallback<1>(Decryptor::kError,
- Decryptor::AudioFrames()));
+ .WillRepeatedly(
+ RunCallback<1>(Decryptor::kError, Decryptor::AudioFrames()));
DecodeAndExpect(encrypted_buffer_, DecodeStatus::DECODE_ERROR);
}
@@ -423,8 +420,8 @@ TEST_F(DecryptingAudioDecoderTest, KeyAdded_DruingPendingDecode) {
// The audio decode callback is returned after the correct decryption key is
// added.
key_added_cb_.Run();
- base::ResetAndReturn(&pending_audio_decode_cb_).Run(
- Decryptor::kNoKey, Decryptor::AudioFrames());
+ base::ResetAndReturn(&pending_audio_decode_cb_)
+ .Run(Decryptor::kNoKey, Decryptor::AudioFrames());
base::RunLoop().RunUntilIdle();
}
diff --git a/chromium/media/filters/decrypting_demuxer_stream.cc b/chromium/media/filters/decrypting_demuxer_stream.cc
index 06009f7a947..12de15c5369 100644
--- a/chromium/media/filters/decrypting_demuxer_stream.cc
+++ b/chromium/media/filters/decrypting_demuxer_stream.cc
@@ -58,7 +58,7 @@ void DecryptingDemuxerStream::Initialize(DemuxerStream* stream,
InitializeDecoderConfig();
if (!cdm_context->GetDecryptor()) {
- DVLOG(2) << __func__ << ": no decryptor";
+ DVLOG(1) << __func__ << ": no decryptor";
state_ = kUninitialized;
base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
return;
@@ -235,8 +235,7 @@ void DecryptingDemuxerStream::DecryptPendingBuffer() {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, kPendingDecrypt) << state_;
decryptor_->Decrypt(
- GetDecryptorStreamType(),
- pending_buffer_to_decrypt_,
+ GetDecryptorStreamType(), pending_buffer_to_decrypt_,
BindToCurrentLoop(
base::Bind(&DecryptingDemuxerStream::DeliverBuffer, weak_this_)));
}
@@ -274,15 +273,17 @@ void DecryptingDemuxerStream::DeliverBuffer(
if (status == Decryptor::kNoKey) {
std::string key_id = pending_buffer_to_decrypt_->decrypt_config()->key_id();
- std::string missing_key_id = base::HexEncode(key_id.data(), key_id.size());
- DVLOG(1) << "DeliverBuffer() - no key for key ID " << missing_key_id;
- MEDIA_LOG(INFO, media_log_) << GetDisplayName() << ": no key for key ID "
- << missing_key_id;
+
+ std::string log_message =
+ "no key for key ID " + base::HexEncode(key_id.data(), key_id.size()) +
+ "; will resume decrypting after new usable key is available";
+ DVLOG(1) << __func__ << ": " << log_message;
+ MEDIA_LOG(INFO, media_log_) << GetDisplayName() << ": " << log_message;
if (need_to_try_again_if_nokey) {
// The |state_| is still kPendingDecrypt.
- MEDIA_LOG(INFO, media_log_) << GetDisplayName()
- << ": key was added, resuming decrypt";
+ MEDIA_LOG(INFO, media_log_)
+ << GetDisplayName() << ": key was added, resuming decrypt";
DecryptPendingBuffer();
return;
}
diff --git a/chromium/media/filters/decrypting_demuxer_stream_unittest.cc b/chromium/media/filters/decrypting_demuxer_stream_unittest.cc
index 2650a45a168..d156adc807f 100644
--- a/chromium/media/filters/decrypting_demuxer_stream_unittest.cc
+++ b/chromium/media/filters/decrypting_demuxer_stream_unittest.cc
@@ -41,8 +41,10 @@ static const uint8_t kFakeIv[DecryptConfig::kDecryptionKeySize] = {0};
static scoped_refptr<DecoderBuffer> CreateFakeEncryptedStreamBuffer(
bool is_clear) {
scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(kFakeBufferSize));
- std::string iv = is_clear ? std::string() :
- std::string(reinterpret_cast<const char*>(kFakeIv), arraysize(kFakeIv));
+ std::string iv = is_clear
+ ? std::string()
+ : std::string(reinterpret_cast<const char*>(kFakeIv),
+ arraysize(kFakeIv));
if (!is_clear) {
buffer->set_decrypt_config(DecryptConfig::CreateCencConfig(
std::string(reinterpret_cast<const char*>(kFakeKeyId),
@@ -227,8 +229,8 @@ class DecryptingDemuxerStreamTest : public testing::Test {
EXPECT_CALL(*input_audio_stream_, Read(_))
.WillRepeatedly(ReturnBuffer(encrypted_buffer_));
EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _))
- .WillRepeatedly(RunCallback<2>(Decryptor::kNoKey,
- scoped_refptr<DecoderBuffer>()));
+ .WillRepeatedly(
+ RunCallback<2>(Decryptor::kNoKey, scoped_refptr<DecoderBuffer>()));
EXPECT_MEDIA_LOG(HasSubstr("DecryptingDemuxerStream: no key for key ID"));
EXPECT_CALL(*this, OnWaitingForDecryptionKey());
demuxer_stream_->Read(base::Bind(&DecryptingDemuxerStreamTest::BufferReady,
@@ -343,8 +345,8 @@ TEST_F(DecryptingDemuxerStreamTest, Read_DecryptError) {
EXPECT_CALL(*input_audio_stream_, Read(_))
.WillRepeatedly(ReturnBuffer(encrypted_buffer_));
EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _))
- .WillRepeatedly(RunCallback<2>(Decryptor::kError,
- scoped_refptr<DecoderBuffer>()));
+ .WillRepeatedly(
+ RunCallback<2>(Decryptor::kError, scoped_refptr<DecoderBuffer>()));
EXPECT_MEDIA_LOG(HasSubstr("DecryptingDemuxerStream: decrypt error"));
ReadAndExpectBufferReadyWith(DemuxerStream::kError, nullptr);
}
diff --git a/chromium/media/filters/decrypting_video_decoder.cc b/chromium/media/filters/decrypting_video_decoder.cc
index 1f4968d5926..132e58e1dd3 100644
--- a/chromium/media/filters/decrypting_video_decoder.cc
+++ b/chromium/media/filters/decrypting_video_decoder.cc
@@ -47,9 +47,9 @@ void DecryptingVideoDecoder::Initialize(
DVLOG(2) << __func__ << ": " << config.AsHumanReadableString();
DCHECK(task_runner_->BelongsToCurrentThread());
- DCHECK(state_ == kUninitialized ||
- state_ == kIdle ||
- state_ == kDecodeFinished) << state_;
+ DCHECK(state_ == kUninitialized || state_ == kIdle ||
+ state_ == kDecodeFinished)
+ << state_;
DCHECK(decode_cb_.is_null());
DCHECK(reset_cb_.is_null());
DCHECK(config.IsValidConfig());
@@ -80,7 +80,7 @@ void DecryptingVideoDecoder::Initialize(
if (state_ == kUninitialized) {
if (!cdm_context->GetDecryptor()) {
- MEDIA_LOG(DEBUG, media_log_) << GetDisplayName() << ": no decryptor";
+ DVLOG(1) << __func__ << ": no decryptor";
base::ResetAndReturn(&init_cb_).Run(false);
return;
}
@@ -102,9 +102,8 @@ void DecryptingVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
const DecodeCB& decode_cb) {
DVLOG(3) << "Decode()";
DCHECK(task_runner_->BelongsToCurrentThread());
- DCHECK(state_ == kIdle ||
- state_ == kDecodeFinished ||
- state_ == kError) << state_;
+ DCHECK(state_ == kIdle || state_ == kDecodeFinished || state_ == kError)
+ << state_;
DCHECK(!decode_cb.is_null());
CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported.";
@@ -129,11 +128,10 @@ void DecryptingVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
void DecryptingVideoDecoder::Reset(const base::Closure& closure) {
DVLOG(2) << "Reset() - state: " << state_;
DCHECK(task_runner_->BelongsToCurrentThread());
- DCHECK(state_ == kIdle ||
- state_ == kPendingDecode ||
- state_ == kWaitingForKey ||
- state_ == kDecodeFinished ||
- state_ == kError) << state_;
+ DCHECK(state_ == kIdle || state_ == kPendingDecode ||
+ state_ == kWaitingForKey || state_ == kDecodeFinished ||
+ state_ == kError)
+ << state_;
DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
DCHECK(reset_cb_.is_null());
@@ -184,12 +182,11 @@ void DecryptingVideoDecoder::FinishInitialization(bool success) {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, kPendingDecoderInit) << state_;
DCHECK(!init_cb_.is_null());
- DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
+ DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished.
if (!success) {
- MEDIA_LOG(DEBUG, media_log_) << GetDisplayName()
- << ": failed to init decoder on decryptor";
+ DVLOG(1) << __func__ << ": failed to init video decoder on decryptor";
base::ResetAndReturn(&init_cb_).Run(false);
decryptor_ = NULL;
state_ = kError;
@@ -197,16 +194,14 @@ void DecryptingVideoDecoder::FinishInitialization(bool success) {
}
decryptor_->RegisterNewKeyCB(
- Decryptor::kVideo,
- BindToCurrentLoop(
- base::Bind(&DecryptingVideoDecoder::OnKeyAdded, weak_this_)));
+ Decryptor::kVideo, BindToCurrentLoop(base::Bind(
+ &DecryptingVideoDecoder::OnKeyAdded, weak_this_)));
// Success!
state_ = kIdle;
base::ResetAndReturn(&init_cb_).Run(true);
}
-
void DecryptingVideoDecoder::DecodePendingBuffer() {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, kPendingDecode) << state_;
@@ -219,8 +214,9 @@ void DecryptingVideoDecoder::DecodePendingBuffer() {
}
decryptor_->DecryptAndDecodeVideo(
- pending_buffer_to_decode_, BindToCurrentLoop(base::Bind(
- &DecryptingVideoDecoder::DeliverFrame, weak_this_, buffer_size)));
+ pending_buffer_to_decode_,
+ BindToCurrentLoop(base::Bind(&DecryptingVideoDecoder::DeliverFrame,
+ weak_this_, buffer_size)));
}
void DecryptingVideoDecoder::DeliverFrame(
@@ -233,9 +229,9 @@ void DecryptingVideoDecoder::DeliverFrame(
DCHECK(!decode_cb_.is_null());
DCHECK(pending_buffer_to_decode_.get());
- TRACE_EVENT_ASYNC_END2(
- "media", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_,
- "buffer_size", buffer_size, "status", status);
+ TRACE_EVENT_ASYNC_END2("media", "DecryptingVideoDecoder::DecodePendingBuffer",
+ trace_id_, "buffer_size", buffer_size, "status",
+ status);
bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
key_added_while_decode_pending_ = false;
@@ -262,10 +258,11 @@ void DecryptingVideoDecoder::DeliverFrame(
if (status == Decryptor::kNoKey) {
std::string key_id =
scoped_pending_buffer_to_decode->decrypt_config()->key_id();
- std::string missing_key_id = base::HexEncode(key_id.data(), key_id.size());
- DVLOG(1) << "DeliverFrame() - no key for key ID " << missing_key_id;
- MEDIA_LOG(INFO, media_log_) << GetDisplayName() << ": no key for key ID "
- << missing_key_id;
+ std::string log_message =
+ "no key for key ID " + base::HexEncode(key_id.data(), key_id.size()) +
+ "; will resume decoding after new usable key is available";
+ DVLOG(1) << __func__ << ": " << log_message;
+ MEDIA_LOG(INFO, media_log_) << GetDisplayName() << ": " << log_message;
// Set |pending_buffer_to_decode_| back as we need to try decoding the
// pending buffer again when new key is added to the decryptor.
@@ -273,8 +270,8 @@ void DecryptingVideoDecoder::DeliverFrame(
if (need_to_try_again_if_nokey_is_returned) {
// The |state_| is still kPendingDecode.
- MEDIA_LOG(INFO, media_log_) << GetDisplayName()
- << ": key was added, resuming decode";
+ MEDIA_LOG(INFO, media_log_)
+ << GetDisplayName() << ": key was added, resuming decode";
DecodePendingBuffer();
return;
}
@@ -331,8 +328,8 @@ void DecryptingVideoDecoder::OnKeyAdded() {
}
if (state_ == kWaitingForKey) {
- MEDIA_LOG(INFO, media_log_) << GetDisplayName()
- << ": key added, resuming decode";
+ MEDIA_LOG(INFO, media_log_)
+ << GetDisplayName() << ": key added, resuming decode";
state_ = kPendingDecode;
DecodePendingBuffer();
}
diff --git a/chromium/media/filters/decrypting_video_decoder_unittest.cc b/chromium/media/filters/decrypting_video_decoder_unittest.cc
index 095dc3acb54..90d131fe88d 100644
--- a/chromium/media/filters/decrypting_video_decoder_unittest.cc
+++ b/chromium/media/filters/decrypting_video_decoder_unittest.cc
@@ -108,9 +108,8 @@ class DecryptingVideoDecoderTest : public testing::Test {
void DecodeAndExpect(scoped_refptr<DecoderBuffer> buffer,
DecodeStatus status) {
EXPECT_CALL(*this, DecodeDone(status));
- decoder_->Decode(buffer,
- base::Bind(&DecryptingVideoDecoderTest::DecodeDone,
- base::Unretained(this)));
+ decoder_->Decode(buffer, base::Bind(&DecryptingVideoDecoderTest::DecodeDone,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
}
@@ -136,8 +135,9 @@ class DecryptingVideoDecoderTest : public testing::Test {
// Sets up expectations and actions to put DecryptingVideoDecoder in an
// active normal decoding state.
void EnterNormalDecodingState() {
- EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(_, _)).WillRepeatedly(
- Invoke(this, &DecryptingVideoDecoderTest::DecryptAndDecodeVideo));
+ EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(_, _))
+ .WillRepeatedly(
+ Invoke(this, &DecryptingVideoDecoderTest::DecryptAndDecodeVideo));
EXPECT_CALL(*this, FrameReady(decoded_video_frame_));
for (int i = 0; i < kDecodingDelay + 1; ++i)
DecodeAndExpect(encrypted_buffer_, DecodeStatus::OK);
@@ -148,8 +148,7 @@ class DecryptingVideoDecoderTest : public testing::Test {
// EnterNormalDecodingState() to work.
void EnterEndOfStreamState() {
// The codec in the |decryptor_| will be flushed.
- EXPECT_CALL(*this, FrameReady(decoded_video_frame_))
- .Times(kDecodingDelay);
+ EXPECT_CALL(*this, FrameReady(decoded_video_frame_)).Times(kDecodingDelay);
DecodeAndExpect(DecoderBuffer::CreateEOSBuffer(), DecodeStatus::OK);
EXPECT_EQ(0, num_frames_in_decryptor_);
}
@@ -181,8 +180,8 @@ class DecryptingVideoDecoderTest : public testing::Test {
void AbortPendingVideoDecodeCB() {
if (!pending_video_decode_cb_.is_null()) {
- base::ResetAndReturn(&pending_video_decode_cb_).Run(
- Decryptor::kSuccess, scoped_refptr<VideoFrame>(NULL));
+ base::ResetAndReturn(&pending_video_decode_cb_)
+ .Run(Decryptor::kSuccess, scoped_refptr<VideoFrame>(NULL));
}
}
@@ -299,8 +298,8 @@ TEST_F(DecryptingVideoDecoderTest, DecryptAndDecode_DecodeError) {
Initialize();
EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(_, _))
- .WillRepeatedly(RunCallback<1>(Decryptor::kError,
- scoped_refptr<VideoFrame>(NULL)));
+ .WillRepeatedly(
+ RunCallback<1>(Decryptor::kError, scoped_refptr<VideoFrame>(NULL)));
DecodeAndExpect(encrypted_buffer_, DecodeStatus::DECODE_ERROR);
@@ -322,8 +321,8 @@ TEST_F(DecryptingVideoDecoderTest, KeyAdded_DuringWaitingForKey) {
EnterWaitingForKeyState();
EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(_, _))
- .WillRepeatedly(RunCallback<1>(Decryptor::kSuccess,
- decoded_video_frame_));
+ .WillRepeatedly(
+ RunCallback<1>(Decryptor::kSuccess, decoded_video_frame_));
EXPECT_CALL(*this, FrameReady(decoded_video_frame_));
EXPECT_CALL(*this, DecodeDone(DecodeStatus::OK));
key_added_cb_.Run();
@@ -337,15 +336,15 @@ TEST_F(DecryptingVideoDecoderTest, KeyAdded_DuringPendingDecode) {
EnterPendingDecodeState();
EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(_, _))
- .WillRepeatedly(RunCallback<1>(Decryptor::kSuccess,
- decoded_video_frame_));
+ .WillRepeatedly(
+ RunCallback<1>(Decryptor::kSuccess, decoded_video_frame_));
EXPECT_CALL(*this, FrameReady(decoded_video_frame_));
EXPECT_CALL(*this, DecodeDone(DecodeStatus::OK));
// The video decode callback is returned after the correct decryption key is
// added.
key_added_cb_.Run();
- base::ResetAndReturn(&pending_video_decode_cb_).Run(Decryptor::kNoKey,
- null_video_frame_);
+ base::ResetAndReturn(&pending_video_decode_cb_)
+ .Run(Decryptor::kNoKey, null_video_frame_);
base::RunLoop().RunUntilIdle();
}
diff --git a/chromium/media/filters/demuxer_perftest.cc b/chromium/media/filters/demuxer_perftest.cc
index bacffe980b3..d1582abc523 100644
--- a/chromium/media/filters/demuxer_perftest.cc
+++ b/chromium/media/filters/demuxer_perftest.cc
@@ -40,9 +40,6 @@ class DemuxerHostImpl : public media::DemuxerHost {
const Ranges<base::TimeDelta>& ranges) override {}
void SetDuration(base::TimeDelta duration) override {}
void OnDemuxerError(media::PipelineStatus error) override {}
- void AddTextStream(media::DemuxerStream* text_stream,
- const media::TextTrackConfig& config) override {}
- void RemoveTextStream(media::DemuxerStream* text_stream) override {}
private:
DISALLOW_COPY_AND_ASSIGN(DemuxerHostImpl);
@@ -185,7 +182,7 @@ static void RunDemuxerBenchmark(const std::string& filename) {
ASSERT_TRUE(data_source.Initialize(file_path));
Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
- base::Bind(&OnEncryptedMediaInitData);
+ base::BindRepeating(&OnEncryptedMediaInitData);
Demuxer::MediaTracksUpdatedCB tracks_updated_cb =
base::Bind(&OnMediaTracksUpdated);
FFmpegDemuxer demuxer(base::ThreadTaskRunnerHandle::Get(), &data_source,
@@ -194,9 +191,8 @@ static void RunDemuxerBenchmark(const std::string& filename) {
{
base::RunLoop run_loop;
- demuxer.Initialize(
- &demuxer_host,
- base::Bind(&QuitLoopWithStatus, run_loop.QuitClosure()), false);
+ demuxer.Initialize(&demuxer_host, base::Bind(&QuitLoopWithStatus,
+ run_loop.QuitClosure()));
run_loop.Run();
}
diff --git a/chromium/media/filters/ffmpeg_demuxer.cc b/chromium/media/filters/ffmpeg_demuxer.cc
index 7402ce16ab5..a81098549b6 100644
--- a/chromium/media/filters/ffmpeg_demuxer.cc
+++ b/chromium/media/filters/ffmpeg_demuxer.cc
@@ -536,7 +536,12 @@ void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) {
buffer->set_timestamp(stream_timestamp - start_time);
- if (packet->flags & AV_PKT_FLAG_DISCARD) {
+ // If the packet is marked for complete discard and it doesn't already have
+ // any discard padding set, mark the DecoderBuffer for complete discard. We
+ // don't want to overwrite any existing discard padding since the discard
+ // padding may refer to frames beyond this packet.
+ if (packet->flags & AV_PKT_FLAG_DISCARD &&
+ buffer->discard_padding() == DecoderBuffer::DiscardPadding()) {
buffer->set_discard_padding(
std::make_pair(kInfiniteDuration, base::TimeDelta()));
if (buffer->timestamp() < base::TimeDelta()) {
@@ -835,21 +840,6 @@ size_t FFmpegDemuxerStream::MemoryUsage() const {
return buffer_queue_.data_size();
}
-TextKind FFmpegDemuxerStream::GetTextKind() const {
- DCHECK_EQ(type_, DemuxerStream::TEXT);
-
- if (stream_->disposition & AV_DISPOSITION_CAPTIONS)
- return kTextCaptions;
-
- if (stream_->disposition & AV_DISPOSITION_DESCRIPTIONS)
- return kTextDescriptions;
-
- if (stream_->disposition & AV_DISPOSITION_METADATA)
- return kTextMetadata;
-
- return kTextSubtitles;
-}
-
std::string FFmpegDemuxerStream::GetMetadata(const char* key) const {
const AVDictionaryEntry* entry =
av_dict_get(stream_->metadata, key, NULL, 0);
@@ -888,7 +878,6 @@ FFmpegDemuxer::FFmpegDemuxer(
media_log_(media_log),
bitrate_(0),
start_time_(kNoTimestamp),
- text_enabled_(false),
duration_known_(false),
encrypted_media_init_data_cb_(encrypted_media_init_data_cb),
media_tracks_updated_cb_(media_tracks_updated_cb),
@@ -916,11 +905,9 @@ std::string FFmpegDemuxer::GetDisplayName() const {
}
void FFmpegDemuxer::Initialize(DemuxerHost* host,
- const PipelineStatusCB& status_cb,
- bool enable_text_tracks) {
+ const PipelineStatusCB& status_cb) {
DCHECK(task_runner_->BelongsToCurrentThread());
host_ = host;
- text_enabled_ = enable_text_tracks;
weak_this_ = cancel_pending_seek_factory_.GetWeakPtr();
// Give a WeakPtr to BlockingUrlProtocol since we'll need to release it on the
@@ -1106,24 +1093,6 @@ base::TimeDelta FFmpegDemuxer::GetStartTime() const {
return std::max(start_time_, base::TimeDelta());
}
-void FFmpegDemuxer::AddTextStreams() {
- DCHECK(task_runner_->BelongsToCurrentThread());
-
- for (const auto& stream : streams_) {
- if (!stream || stream->type() != DemuxerStream::TEXT)
- continue;
-
- TextKind kind = stream->GetTextKind();
- std::string title = stream->GetMetadata("title");
- std::string language = stream->GetMetadata("language");
-
- // TODO: Implement "id" metadata in FFMPEG.
- // See: http://crbug.com/323183
- host_->AddTextStream(stream.get(),
- TextTrackConfig(kind, title, language, std::string()));
- }
-}
-
int64_t FFmpegDemuxer::GetMemoryUsage() const {
int64_t allocation_size = 0;
for (const auto& stream : streams_) {
@@ -1308,10 +1277,8 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
#endif
} else if (codec_type == AVMEDIA_TYPE_SUBTITLE) {
detected_text_track_count++;
- if (codec_id != AV_CODEC_ID_WEBVTT || !text_enabled_) {
- stream->discard = AVDISCARD_ALL;
- continue;
- }
+ stream->discard = AVDISCARD_ALL;
+ continue;
} else {
stream->discard = AVDISCARD_ALL;
continue;
@@ -1436,9 +1403,6 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
return;
}
- if (text_enabled_)
- AddTextStreams();
-
if (format_context->duration != kNoFFmpegTimestamp) {
// If there is a duration value in the container use that to find the
// maximum between it and the duration from A/V streams.
diff --git a/chromium/media/filters/ffmpeg_demuxer.h b/chromium/media/filters/ffmpeg_demuxer.h
index 425958d0244..01579ab0763 100644
--- a/chromium/media/filters/ffmpeg_demuxer.h
+++ b/chromium/media/filters/ffmpeg_demuxer.h
@@ -214,8 +214,7 @@ class MEDIA_EXPORT FFmpegDemuxer : public Demuxer {
// Demuxer implementation.
std::string GetDisplayName() const override;
void Initialize(DemuxerHost* host,
- const PipelineStatusCB& status_cb,
- bool enable_text_tracks) override;
+ const PipelineStatusCB& status_cb) override;
void AbortPendingReads() override;
void Stop() override;
void StartWaitingForSeek(base::TimeDelta seek_time) override;
@@ -370,9 +369,6 @@ class MEDIA_EXPORT FFmpegDemuxer : public Demuxer {
// time if the file doesn't have an association to Time.
base::Time timeline_offset_;
- // Whether text streams have been enabled for this demuxer.
- bool text_enabled_;
-
// Set if we know duration of the audio stream. Used when processing end of
// stream -- at this moment we definitely know duration.
bool duration_known_;
diff --git a/chromium/media/filters/ffmpeg_demuxer_unittest.cc b/chromium/media/filters/ffmpeg_demuxer_unittest.cc
index b09816a3ba3..24abaff1294 100644
--- a/chromium/media/filters/ffmpeg_demuxer_unittest.cc
+++ b/chromium/media/filters/ffmpeg_demuxer_unittest.cc
@@ -136,34 +136,27 @@ class FFmpegDemuxerTest : public testing::Test {
MOCK_METHOD1(CheckPoint, void(int v));
- void InitializeDemuxerInternal(bool enable_text,
- media::PipelineStatus expected_pipeline_status,
+ void InitializeDemuxerInternal(media::PipelineStatus expected_pipeline_status,
base::Time timeline_offset) {
if (expected_pipeline_status == PIPELINE_OK)
EXPECT_CALL(host_, SetDuration(_)).Times(AnyNumber());
WaitableMessageLoopEvent event;
- demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), enable_text);
+ demuxer_->Initialize(&host_, event.GetPipelineStatusCB());
demuxer_->timeline_offset_ = timeline_offset;
event.RunAndWaitForStatus(expected_pipeline_status);
}
void InitializeDemuxer() {
- InitializeDemuxerInternal(/*enable_text=*/false, PIPELINE_OK, base::Time());
- }
-
- void InitializeDemuxerWithText() {
- InitializeDemuxerInternal(/*enable_text=*/true, PIPELINE_OK, base::Time());
+ InitializeDemuxerInternal(PIPELINE_OK, base::Time());
}
void InitializeDemuxerWithTimelineOffset(base::Time timeline_offset) {
- InitializeDemuxerInternal(/*enable_text=*/false, PIPELINE_OK,
- timeline_offset);
+ InitializeDemuxerInternal(PIPELINE_OK, timeline_offset);
}
void InitializeDemuxerAndExpectPipelineStatus(
media::PipelineStatus expected_pipeline_status) {
- InitializeDemuxerInternal(/*enable_text=*/false, expected_pipeline_status,
- base::Time());
+ InitializeDemuxerInternal(expected_pipeline_status, base::Time());
}
MOCK_METHOD2(OnReadDoneCalled, void(int, int64_t));
@@ -304,8 +297,9 @@ class FFmpegDemuxerTest : public testing::Test {
CreateDataSource(name);
- Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb = base::Bind(
- &FFmpegDemuxerTest::OnEncryptedMediaInitData, base::Unretained(this));
+ Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
+ base::BindRepeating(&FFmpegDemuxerTest::OnEncryptedMediaInitData,
+ base::Unretained(this));
Demuxer::MediaTracksUpdatedCB tracks_updated_cb = base::Bind(
&FFmpegDemuxerTest::OnMediaTracksUpdated, base::Unretained(this));
@@ -337,7 +331,7 @@ TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) {
// Simulate avformat_open_input() failing.
CreateDemuxer("ten_byte_file");
WaitableMessageLoopEvent event;
- demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
+ demuxer_->Initialize(&host_, event.GetPipelineStatusCB());
event.RunAndWaitForStatus(DEMUXER_ERROR_COULD_NOT_OPEN);
}
@@ -345,7 +339,7 @@ TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) {
// Open a file with no streams whatsoever.
CreateDemuxer("no_streams.webm");
WaitableMessageLoopEvent event;
- demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
+ demuxer_->Initialize(&host_, event.GetPipelineStatusCB());
event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
}
@@ -353,7 +347,7 @@ TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) {
// Open a file containing streams but none of which are audio/video streams.
CreateDemuxer("no_audio_video.webm");
WaitableMessageLoopEvent event;
- demuxer_->Initialize(&host_, event.GetPipelineStatusCB(), true);
+ demuxer_->Initialize(&host_, event.GetPipelineStatusCB());
event.RunAndWaitForStatus(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
}
@@ -438,35 +432,6 @@ TEST_F(FFmpegDemuxerTest, Initialize_Multitrack) {
}
#endif
-TEST_F(FFmpegDemuxerTest, Initialize_MultitrackText) {
- // Open a file containing the following streams:
- // Stream #0: Video (VP8)
- // Stream #1: Audio (Vorbis)
- // Stream #2: Text (WebVTT)
-
- CreateDemuxer("bear-vp8-webvtt.webm");
- DemuxerStream* text_stream = NULL;
- EXPECT_CALL(host_, AddTextStream(_, _))
- .WillOnce(SaveArg<0>(&text_stream));
- InitializeDemuxerWithText();
- ASSERT_TRUE(text_stream);
- EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
-
- // Video stream should be VP8.
- DemuxerStream* stream = GetStream(DemuxerStream::VIDEO);
- ASSERT_TRUE(stream);
- EXPECT_EQ(DemuxerStream::VIDEO, stream->type());
- EXPECT_EQ(kCodecVP8, stream->video_decoder_config().codec());
-
- // Audio stream should be Vorbis.
- stream = GetStream(DemuxerStream::AUDIO);
- ASSERT_TRUE(stream);
- EXPECT_EQ(DemuxerStream::AUDIO, stream->type());
- EXPECT_EQ(kCodecVorbis, stream->audio_decoder_config().codec());
-
- EXPECT_EQ(3u, demuxer_->GetAllStreams().size());
-}
-
TEST_F(FFmpegDemuxerTest, Initialize_Encrypted) {
EXPECT_CALL(*this,
OnEncryptedMediaInitData(
@@ -556,23 +521,6 @@ TEST_F(FFmpegDemuxerTest, Read_Video) {
EXPECT_EQ(148778, demuxer_->GetMemoryUsage());
}
-TEST_F(FFmpegDemuxerTest, Read_Text) {
- // We test that on a successful text packet read.
- CreateDemuxer("bear-vp8-webvtt.webm");
- DemuxerStream* text_stream = NULL;
- EXPECT_CALL(host_, AddTextStream(_, _))
- .WillOnce(SaveArg<0>(&text_stream));
- InitializeDemuxerWithText();
- ASSERT_TRUE(text_stream);
- EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
-
- text_stream->Read(NewReadCB(FROM_HERE, 31, 0, true));
- base::RunLoop().Run();
-
- text_stream->Read(NewReadCB(FROM_HERE, 19, 500000, true));
- base::RunLoop().Run();
-}
-
TEST_F(FFmpegDemuxerTest, SeekInitialized_NoVideoStartTime) {
CreateDemuxer("audio-start-time-only.webm");
InitializeDemuxer();
@@ -951,39 +899,6 @@ TEST_F(FFmpegDemuxerTest, Read_DiscardDisabledVideoStream) {
EXPECT_LT(bytes_read_with_video_disabled, bytes_read_with_video_enabled);
}
-// WebM text track discarding doesn't work in ffmpeg. http://crbug.com/681886.
-TEST_F(FFmpegDemuxerTest, DISABLED_Read_DiscardDisabledTextStream) {
- // This test case reads the same video frame twice, first with the text track
- // enabled, then with the text track disabled. When the text track is
- // disabled, FFmpegDemuxer sets the AVDISCARD_ALL flag on the corresponding
- // stream, which allows FFmpeg to choose the initial reading position closer
- // to the requested video frame (i.e. closer to seek_target), since it doesn't
- // need to consider key frames for the text stream. This results in less data
- // being read compared to the case with enabled text track.
- const base::TimeDelta seek_target = base::TimeDelta::FromMilliseconds(805);
-
- CreateDemuxer("bear-vp8-webvtt.webm");
- EXPECT_CALL(host_, AddTextStream(_, _));
- InitializeDemuxerWithText();
- Seek(seek_target);
- GetStream(DemuxerStream::VIDEO)
- ->Read(NewReadCB(FROM_HERE, 5425, 801000, true));
- base::RunLoop().Run();
- auto bytes_read_with_text_enabled = data_source_->bytes_read_for_testing();
-
- Shutdown();
-
- CreateDemuxer("bear-vp8-webvtt.webm");
- InitializeDemuxer();
- Seek(seek_target);
- GetStream(DemuxerStream::VIDEO)
- ->Read(NewReadCB(FROM_HERE, 5425, 801000, true));
- base::RunLoop().Run();
- auto bytes_read_with_text_disabled = data_source_->bytes_read_for_testing();
-
- EXPECT_LT(bytes_read_with_text_disabled, bytes_read_with_text_enabled);
-}
-
TEST_F(FFmpegDemuxerTest, Read_EndOfStream) {
// Verify that end of stream buffers are created.
CreateDemuxer("bear-320x240.webm");
@@ -991,26 +906,6 @@ TEST_F(FFmpegDemuxerTest, Read_EndOfStream) {
ReadUntilEndOfStream(GetStream(DemuxerStream::AUDIO));
}
-TEST_F(FFmpegDemuxerTest, Read_EndOfStreamText) {
- // Verify that end of stream buffers are created.
- CreateDemuxer("bear-vp8-webvtt.webm");
- DemuxerStream* text_stream = NULL;
- EXPECT_CALL(host_, AddTextStream(_, _))
- .WillOnce(SaveArg<0>(&text_stream));
- InitializeDemuxerWithText();
- ASSERT_TRUE(text_stream);
- EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
-
- bool got_eos_buffer = false;
- const int kMaxBuffers = 10;
- for (int i = 0; !got_eos_buffer && i < kMaxBuffers; i++) {
- text_stream->Read(base::Bind(&EosOnReadDone, &got_eos_buffer));
- base::RunLoop().Run();
- }
-
- EXPECT_TRUE(got_eos_buffer);
-}
-
TEST_F(FFmpegDemuxerTest, Read_EndOfStream_NoDuration) {
// Verify that end of stream buffers are created.
CreateDemuxer("bear-320x240.webm");
@@ -1111,58 +1006,6 @@ TEST_F(FFmpegDemuxerTest, CancelledSeek) {
event.RunAndWaitForStatus(PIPELINE_OK);
}
-TEST_F(FFmpegDemuxerTest, SeekText) {
- // We're testing that the demuxer frees all queued packets when it receives
- // a Seek().
- CreateDemuxer("bear-vp8-webvtt.webm");
- DemuxerStream* text_stream = NULL;
- EXPECT_CALL(host_, AddTextStream(_, _))
- .WillOnce(SaveArg<0>(&text_stream));
- InitializeDemuxerWithText();
- ASSERT_TRUE(text_stream);
- EXPECT_EQ(DemuxerStream::TEXT, text_stream->type());
-
- // Get our streams.
- DemuxerStream* video = GetStream(DemuxerStream::VIDEO);
- DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
- ASSERT_TRUE(video);
- ASSERT_TRUE(audio);
-
- // Read a text packet and release it.
- text_stream->Read(NewReadCB(FROM_HERE, 31, 0, true));
- base::RunLoop().Run();
-
- // Issue a simple forward seek, which should discard queued packets.
- WaitableMessageLoopEvent event;
- demuxer_->Seek(base::TimeDelta::FromMicroseconds(1000000),
- event.GetPipelineStatusCB());
- event.RunAndWaitForStatus(PIPELINE_OK);
-
- // Audio read #1.
- audio->Read(NewReadCB(FROM_HERE, 145, 803000, true));
- base::RunLoop().Run();
-
- // Audio read #2.
- audio->Read(NewReadCB(FROM_HERE, 148, 826000, true));
- base::RunLoop().Run();
-
- // Video read #1.
- video->Read(NewReadCB(FROM_HERE, 5425, 801000, true));
- base::RunLoop().Run();
-
- // Video read #2.
- video->Read(NewReadCB(FROM_HERE, 1906, 834000, false));
- base::RunLoop().Run();
-
- // Text read #1.
- text_stream->Read(NewReadCB(FROM_HERE, 19, 1000000, true));
- base::RunLoop().Run();
-
- // Text read #2.
- text_stream->Read(NewReadCB(FROM_HERE, 19, 1500000, true));
- base::RunLoop().Run();
-}
-
TEST_F(FFmpegDemuxerTest, Stop) {
// Tests that calling Read() on a stopped demuxer stream immediately deletes
// the callback.
diff --git a/chromium/media/filters/ffmpeg_glue_unittest.cc b/chromium/media/filters/ffmpeg_glue_unittest.cc
index e51019cd661..660b4d4654a 100644
--- a/chromium/media/filters/ffmpeg_glue_unittest.cc
+++ b/chromium/media/filters/ffmpeg_glue_unittest.cc
@@ -10,7 +10,7 @@
#include "base/logging.h"
#include "base/macros.h"
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
#include "media/base/container_names.h"
#include "media/base/mock_filters.h"
#include "media/base/test_data_util.h"
diff --git a/chromium/media/filters/frame_buffer_pool.cc b/chromium/media/filters/frame_buffer_pool.cc
index 84c09973a1d..1bcbc8df261 100644
--- a/chromium/media/filters/frame_buffer_pool.cc
+++ b/chromium/media/filters/frame_buffer_pool.cc
@@ -19,8 +19,12 @@
namespace media {
struct FrameBufferPool::FrameBuffer {
- std::vector<uint8_t> data;
- std::vector<uint8_t> alpha_data;
+ // Not using std::vector<uint8_t> as resize() calls take a really long time
+ // for large buffers.
+ std::unique_ptr<uint8_t[]> data;
+ size_t data_size = 0u;
+ std::unique_ptr<uint8_t[]> alpha_data;
+ size_t alpha_data_size = 0u;
bool held_by_library = false;
// Needs to be a counter since a frame buffer might be used multiple times.
int held_by_frame = 0;
@@ -63,12 +67,17 @@ uint8_t* FrameBufferPool::GetFrameBuffer(size_t min_size, void** fb_priv) {
// Resize the frame buffer if necessary.
frame_buffer->held_by_library = true;
- if (frame_buffer->data.size() < min_size)
- frame_buffer->data.resize(min_size);
+ if (frame_buffer->data_size < min_size) {
+ // Free the existing |data| first so that the memory can be reused,
+ // if possible. Note that the new array is purposely not initialized.
+ frame_buffer->data.reset();
+ frame_buffer->data.reset(new uint8_t[min_size]);
+ frame_buffer->data_size = min_size;
+ }
// Provide the client with a private identifier.
*fb_priv = frame_buffer.get();
- return frame_buffer->data.data();
+ return frame_buffer->data.get();
}
void FrameBufferPool::ReleaseFrameBuffer(void* fb_priv) {
@@ -89,9 +98,14 @@ uint8_t* FrameBufferPool::AllocateAlphaPlaneForFrameBuffer(size_t min_size,
auto* frame_buffer = static_cast<FrameBuffer*>(fb_priv);
DCHECK(IsUsed(frame_buffer));
- if (frame_buffer->alpha_data.size() < min_size)
- frame_buffer->alpha_data.resize(min_size);
- return frame_buffer->alpha_data.data();
+ if (frame_buffer->alpha_data_size < min_size) {
+ // Free the existing |alpha_data| first so that the memory can be reused,
+ // if possible. Note that the new array is purposely not initialized.
+ frame_buffer->alpha_data.reset();
+ frame_buffer->alpha_data.reset(new uint8_t[min_size]);
+ frame_buffer->alpha_data_size = min_size;
+ }
+ return frame_buffer->alpha_data.get();
}
base::Closure FrameBufferPool::CreateFrameCallback(void* fb_priv) {
@@ -121,8 +135,8 @@ bool FrameBufferPool::OnMemoryDump(
size_t bytes_reserved = 0;
for (const auto& frame_buffer : frame_buffers_) {
if (IsUsed(frame_buffer.get()))
- bytes_used += frame_buffer->data.size();
- bytes_reserved += frame_buffer->data.size();
+ bytes_used += frame_buffer->data_size + frame_buffer->alpha_data_size;
+ bytes_reserved += frame_buffer->data_size + frame_buffer->alpha_data_size;
}
memory_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
diff --git a/chromium/media/filters/frame_processor.cc b/chromium/media/filters/frame_processor.cc
index c58ef7e0236..dc6c65f77a2 100644
--- a/chromium/media/filters/frame_processor.cc
+++ b/chromium/media/filters/frame_processor.cc
@@ -653,8 +653,9 @@ bool FrameProcessor::ProcessFrame(scoped_refptr<StreamParserBuffer> frame,
// index.html#sourcebuffer-coded-frame-processing
while (true) {
// 1. Loop Top:
- // Otherwise case: (See SourceBufferState's |auto_update_timestamp_offset_|,
- // too).
+ // Otherwise case: (See also SourceBufferState::OnNewBuffer's conditional
+ // modification of timestamp_offset after frame processing returns, when
+ // generate_timestamps_flag is true).
// 1.1. Let presentation timestamp be a double precision floating point
// representation of the coded frame's presentation timestamp in
// seconds.
@@ -1020,8 +1021,10 @@ bool FrameProcessor::ProcessFrame(scoped_refptr<StreamParserBuffer> frame,
group_end_timestamp_ = frame_end_timestamp;
DCHECK(group_end_timestamp_ >= base::TimeDelta());
- // Step 21 is currently handled differently. See SourceBufferState's
- // |auto_update_timestamp_offset_|.
+ // TODO(wolenetz): Step 21 is currently approximated by predicted
+ // frame_end_time by SourceBufferState::OnNewBuffers(). See
+ // https://crbug.com/850316.
+
return true;
}
diff --git a/chromium/media/filters/frame_processor_unittest.cc b/chromium/media/filters/frame_processor_unittest.cc
index 837973c02ee..0989f0ea76d 100644
--- a/chromium/media/filters/frame_processor_unittest.cc
+++ b/chromium/media/filters/frame_processor_unittest.cc
@@ -352,15 +352,16 @@ class FrameProcessorTest
CHANNEL_LAYOUT_STEREO, 1000,
EmptyExtraData(), Unencrypted());
frame_processor_->OnPossibleAudioConfigUpdate(decoder_config);
- ASSERT_TRUE(audio_->UpdateAudioConfig(decoder_config, &media_log_));
+ ASSERT_TRUE(
+ audio_->UpdateAudioConfig(decoder_config, false, &media_log_));
break;
}
case DemuxerStream::VIDEO: {
ASSERT_FALSE(video_);
video_.reset(
new ChunkDemuxerStream(DemuxerStream::VIDEO, "2", range_api_));
- ASSERT_TRUE(
- video_->UpdateVideoConfig(TestVideoConfig::Normal(), &media_log_));
+ ASSERT_TRUE(video_->UpdateVideoConfig(TestVideoConfig::Normal(), false,
+ &media_log_));
break;
}
// TODO(wolenetz): Test text coded frame processing.
diff --git a/chromium/media/filters/gpu_video_decoder.cc b/chromium/media/filters/gpu_video_decoder.cc
index b16ed0a110e..a5783c95b67 100644
--- a/chromium/media/filters/gpu_video_decoder.cc
+++ b/chromium/media/filters/gpu_video_decoder.cc
@@ -27,7 +27,6 @@
#include "media/base/media_log.h"
#include "media/base/media_switches.h"
#include "media/base/pipeline_status.h"
-#include "media/base/surface_manager.h"
#include "media/base/video_decoder_config.h"
#include "media/base/video_util.h"
#include "media/media_buildflags.h"
@@ -146,6 +145,10 @@ static void ReportGpuVideoDecoderInitializeStatusToUMAAndRunCB(
cb.Run(success);
}
+bool GpuVideoDecoder::IsPlatformDecoder() const {
+ return true;
+}
+
std::string GpuVideoDecoder::GetDisplayName() const {
return kDecoderName;
}
diff --git a/chromium/media/filters/gpu_video_decoder.h b/chromium/media/filters/gpu_video_decoder.h
index 65a86c9f29d..494cc021671 100644
--- a/chromium/media/filters/gpu_video_decoder.h
+++ b/chromium/media/filters/gpu_video_decoder.h
@@ -20,7 +20,6 @@
#include "gpu/command_buffer/common/sync_token.h"
#include "media/base/overlay_info.h"
#include "media/base/pipeline_status.h"
-#include "media/base/surface_manager.h"
#include "media/base/video_decoder.h"
#include "media/video/video_decode_accelerator.h"
@@ -56,6 +55,7 @@ class MEDIA_EXPORT GpuVideoDecoder
// VideoDecoder implementation.
std::string GetDisplayName() const override;
+ bool IsPlatformDecoder() const override;
void Initialize(
const VideoDecoderConfig& config,
bool low_delay,
diff --git a/chromium/media/filters/pipeline_controller.cc b/chromium/media/filters/pipeline_controller.cc
index 706b58138af..e204dc931b8 100644
--- a/chromium/media/filters/pipeline_controller.cc
+++ b/chromium/media/filters/pipeline_controller.cc
@@ -72,6 +72,7 @@ void PipelineController::Seek(base::TimeDelta time, bool time_updated) {
if (time_updated)
pending_time_updated_ = true;
pending_seeked_cb_ = true;
+ pending_seek_except_start_ = true;
// If we are already seeking to |time|, and the media is static, elide the
// seek.
@@ -111,6 +112,11 @@ bool PipelineController::IsStable() {
return state_ == State::PLAYING;
}
+bool PipelineController::IsPendingSeek() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return pending_seek_except_start_;
+}
+
bool PipelineController::IsSuspended() {
DCHECK(thread_checker_.CalledOnValidThread());
return (pending_suspend_ || state_ == State::SUSPENDING ||
@@ -287,6 +293,7 @@ void PipelineController::Dispatch() {
// immediately.
pending_startup_ = false;
pending_seeked_cb_ = false;
+ pending_seek_except_start_ = false;
bool was_pending_time_updated = pending_time_updated_;
pending_time_updated_ = false;
seeked_cb_.Run(was_pending_time_updated);
@@ -301,6 +308,7 @@ void PipelineController::Stop() {
demuxer_ = nullptr;
waiting_for_seek_ = false;
pending_seeked_cb_ = false;
+ pending_seek_except_start_ = false;
pending_time_updated_ = false;
pending_seek_ = false;
pending_suspend_ = false;
diff --git a/chromium/media/filters/pipeline_controller.h b/chromium/media/filters/pipeline_controller.h
index bf80dbb66a9..92a420a079f 100644
--- a/chromium/media/filters/pipeline_controller.h
+++ b/chromium/media/filters/pipeline_controller.h
@@ -114,6 +114,10 @@ class MEDIA_EXPORT PipelineController {
// Returns true if the current target state is suspended.
bool IsSuspended();
+ // Returns true if Seek() was called and there is a seek operation which has
+ // not yet completed.
+ bool IsPendingSeek();
+
// Returns true if |pipeline_| is suspended.
bool IsPipelineSuspended();
@@ -189,6 +193,9 @@ class MEDIA_EXPORT PipelineController {
// issued at the next stable state.
bool pending_seeked_cb_ = false;
+ // Indicates that a seek has occurred from an explicit call to Seek().
+ bool pending_seek_except_start_ = false;
+
// Indicates that time has been changed by a seek, which will be reported at
// the next seeked callback.
bool pending_time_updated_ = false;
diff --git a/chromium/media/filters/source_buffer_state.cc b/chromium/media/filters/source_buffer_state.cc
index aa7d625c7b2..2c86688c04d 100644
--- a/chromium/media/filters/source_buffer_state.cc
+++ b/chromium/media/filters/source_buffer_state.cc
@@ -55,6 +55,17 @@ bool CheckBytestreamTrackIds(
return true;
}
+unsigned GetMSEBufferSizeLimitIfExists(base::StringPiece switch_string) {
+ auto* command_line = base::CommandLine::ForCurrentProcess();
+ unsigned memory_limit;
+ if (command_line->HasSwitch(switch_string) &&
+ base::StringToUint(command_line->GetSwitchValueASCII(switch_string),
+ &memory_limit)) {
+ return memory_limit * 1024 * 1024;
+ }
+ return 0;
+}
+
} // namespace
// List of time ranges for each SourceBuffer.
@@ -126,8 +137,7 @@ SourceBufferState::SourceBufferState(
frame_processor_(frame_processor.release()),
create_demuxer_stream_cb_(create_demuxer_stream_cb),
media_log_(media_log),
- state_(UNINITIALIZED),
- auto_update_timestamp_offset_(false) {
+ state_(UNINITIALIZED) {
DCHECK(!create_demuxer_stream_cb_.is_null());
DCHECK(frame_processor_);
}
@@ -137,47 +147,32 @@ SourceBufferState::~SourceBufferState() {
}
void SourceBufferState::Init(
- const StreamParser::InitCB& init_cb,
+ StreamParser::InitCB init_cb,
const std::string& expected_codecs,
const StreamParser::EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
const NewTextTrackCB& new_text_track_cb) {
DCHECK_EQ(state_, UNINITIALIZED);
- init_cb_ = init_cb;
+ init_cb_ = std::move(init_cb);
encrypted_media_init_data_cb_ = encrypted_media_init_data_cb;
new_text_track_cb_ = new_text_track_cb;
+ state_ = PENDING_PARSER_CONFIG;
+ InitializeParser(expected_codecs);
+}
- std::vector<std::string> expected_codecs_parsed;
- SplitCodecsToVector(expected_codecs, &expected_codecs_parsed, false);
+void SourceBufferState::ChangeType(
+ std::unique_ptr<StreamParser> new_stream_parser,
+ const std::string& new_expected_codecs) {
+ DCHECK_GE(state_, PENDING_PARSER_CONFIG);
+ DCHECK_NE(state_, PENDING_PARSER_INIT);
+ DCHECK(!parsing_media_segment_);
- std::vector<AudioCodec> expected_acodecs;
- std::vector<VideoCodec> expected_vcodecs;
- for (const auto& codec_id : expected_codecs_parsed) {
- AudioCodec acodec = StringToAudioCodec(codec_id);
- if (acodec != kUnknownAudioCodec) {
- expected_audio_codecs_.push_back(acodec);
- continue;
- }
- VideoCodec vcodec = StringToVideoCodec(codec_id);
- if (vcodec != kUnknownVideoCodec) {
- expected_video_codecs_.push_back(vcodec);
- continue;
- }
- MEDIA_LOG(INFO, media_log_) << "Unrecognized media codec: " << codec_id;
- }
+ // If this source buffer has already handled an initialization segment, avoid
+ // running |init_cb_| again later.
+ if (state_ == PARSER_INITIALIZED)
+ state_ = PENDING_PARSER_RECONFIG;
- state_ = PENDING_PARSER_CONFIG;
- stream_parser_->Init(
- base::Bind(&SourceBufferState::OnSourceInitDone, base::Unretained(this)),
- base::Bind(&SourceBufferState::OnNewConfigs, base::Unretained(this),
- expected_codecs),
- base::Bind(&SourceBufferState::OnNewBuffers, base::Unretained(this)),
- new_text_track_cb_.is_null(),
- base::Bind(&SourceBufferState::OnEncryptedMediaInitData,
- base::Unretained(this)),
- base::Bind(&SourceBufferState::OnNewMediaSegment, base::Unretained(this)),
- base::Bind(&SourceBufferState::OnEndOfMediaSegment,
- base::Unretained(this)),
- media_log_);
+ stream_parser_ = std::move(new_stream_parser);
+ InitializeParser(new_expected_codecs);
}
void SourceBufferState::SetSequenceMode(bool sequence_mode) {
@@ -545,6 +540,46 @@ bool SourceBufferState::IsSeekWaitingForData() const {
return false;
}
+void SourceBufferState::InitializeParser(const std::string& expected_codecs) {
+ expected_audio_codecs_.clear();
+ expected_video_codecs_.clear();
+
+ std::vector<std::string> expected_codecs_parsed;
+ SplitCodecsToVector(expected_codecs, &expected_codecs_parsed, false);
+
+ std::vector<AudioCodec> expected_acodecs;
+ std::vector<VideoCodec> expected_vcodecs;
+ for (const auto& codec_id : expected_codecs_parsed) {
+ AudioCodec acodec = StringToAudioCodec(codec_id);
+ if (acodec != kUnknownAudioCodec) {
+ expected_audio_codecs_.push_back(acodec);
+ continue;
+ }
+ VideoCodec vcodec = StringToVideoCodec(codec_id);
+ if (vcodec != kUnknownVideoCodec) {
+ expected_video_codecs_.push_back(vcodec);
+ continue;
+ }
+ MEDIA_LOG(INFO, media_log_) << "Unrecognized media codec: " << codec_id;
+ }
+
+ stream_parser_->Init(
+ base::BindOnce(&SourceBufferState::OnSourceInitDone,
+ base::Unretained(this)),
+ base::BindRepeating(&SourceBufferState::OnNewConfigs,
+ base::Unretained(this), expected_codecs),
+ base::BindRepeating(&SourceBufferState::OnNewBuffers,
+ base::Unretained(this)),
+ new_text_track_cb_.is_null(),
+ base::BindRepeating(&SourceBufferState::OnEncryptedMediaInitData,
+ base::Unretained(this)),
+ base::BindRepeating(&SourceBufferState::OnNewMediaSegment,
+ base::Unretained(this)),
+ base::BindRepeating(&SourceBufferState::OnEndOfMediaSegment,
+ base::Unretained(this)),
+ media_log_);
+}
+
bool SourceBufferState::OnNewConfigs(
std::string expected_codecs,
std::unique_ptr<MediaTracks> tracks,
@@ -576,6 +611,11 @@ bool SourceBufferState::OnNewConfigs(
std::vector<AudioCodec> expected_acodecs = expected_audio_codecs_;
std::vector<VideoCodec> expected_vcodecs = expected_video_codecs_;
+ // TODO(wolenetz): Once codec strictness is relaxed, we can change
+ // |allow_codec_changes| to always be true. Until then, we only allow codec
+ // changes on explicit ChangeType().
+ const bool allow_codec_changes = state_ == PENDING_PARSER_RECONFIG;
+
FrameProcessor::TrackIdChanges track_id_changes;
for (const auto& track : tracks->tracks()) {
const auto& track_id = track->bytestream_track_id();
@@ -635,7 +675,8 @@ bool SourceBufferState::OnNewConfigs(
track->set_id(stream->media_track_id());
frame_processor_->OnPossibleAudioConfigUpdate(audio_config);
- success &= stream->UpdateAudioConfig(audio_config, media_log_);
+ success &= stream->UpdateAudioConfig(audio_config, allow_codec_changes,
+ media_log_);
} else if (track->type() == MediaTrack::Video) {
VideoDecoderConfig video_config = tracks->getVideoConfig(track_id);
DVLOG(1) << "Video track_id=" << track_id
@@ -690,7 +731,8 @@ bool SourceBufferState::OnNewConfigs(
}
track->set_id(stream->media_track_id());
- success &= stream->UpdateVideoConfig(video_config, media_log_);
+ success &= stream->UpdateVideoConfig(video_config, allow_codec_changes,
+ media_log_);
} else {
MEDIA_LOG(ERROR, media_log_) << "Error: unsupported media track type "
<< track->type();
@@ -798,6 +840,8 @@ bool SourceBufferState::OnNewConfigs(
if (success) {
if (state_ == PENDING_PARSER_CONFIG)
state_ = PENDING_PARSER_INIT;
+ if (state_ == PENDING_PARSER_RECONFIG)
+ state_ = PENDING_PARSER_REINIT;
DCHECK(!init_segment_received_cb_.is_null());
init_segment_received_cb_.Run(std::move(tracks));
}
@@ -806,32 +850,24 @@ bool SourceBufferState::OnNewConfigs(
}
void SourceBufferState::SetStreamMemoryLimits() {
- auto* cmd_line = base::CommandLine::ForCurrentProcess();
-
- std::string audio_buf_limit_switch =
- cmd_line->GetSwitchValueASCII(switches::kMSEAudioBufferSizeLimit);
- unsigned audio_buf_size_limit = 0;
- if (base::StringToUint(audio_buf_limit_switch, &audio_buf_size_limit) &&
- audio_buf_size_limit > 0) {
+ size_t audio_buf_size_limit =
+ GetMSEBufferSizeLimitIfExists(switches::kMSEAudioBufferSizeLimitMb);
+ if (audio_buf_size_limit) {
MEDIA_LOG(INFO, media_log_)
<< "Custom audio per-track SourceBuffer size limit="
<< audio_buf_size_limit;
- for (const auto& it : audio_streams_) {
+ for (const auto& it : audio_streams_)
it.second->SetStreamMemoryLimit(audio_buf_size_limit);
- }
}
- std::string video_buf_limit_switch =
- cmd_line->GetSwitchValueASCII(switches::kMSEVideoBufferSizeLimit);
- unsigned video_buf_size_limit = 0;
- if (base::StringToUint(video_buf_limit_switch, &video_buf_size_limit) &&
- video_buf_size_limit > 0) {
+ size_t video_buf_size_limit =
+ GetMSEBufferSizeLimitIfExists(switches::kMSEVideoBufferSizeLimitMb);
+ if (video_buf_size_limit) {
MEDIA_LOG(INFO, media_log_)
<< "Custom video per-track SourceBuffer size limit="
<< video_buf_size_limit;
- for (const auto& it : video_streams_) {
+ for (const auto& it : video_streams_)
it.second->SetStreamMemoryLimit(video_buf_size_limit);
- }
}
}
@@ -886,9 +922,10 @@ bool SourceBufferState::OnNewBuffers(
*timestamp_offset_during_append_;
// Calculate the new timestamp offset for audio/video tracks if the stream
- // parser has requested automatic updates.
- TimeDelta new_timestamp_offset = timestamp_offset_before_processing;
- if (auto_update_timestamp_offset_) {
+ // parser corresponds to MSE MIME type with 'Generate Timestamps Flag' set
+ // true.
+ TimeDelta predicted_timestamp_offset = timestamp_offset_before_processing;
+ if (generate_timestamps_flag()) {
TimeDelta min_end_timestamp = kNoTimestamp;
for (const auto& it : buffer_queue_map) {
const StreamParser::BufferQueue& bufq = it.second;
@@ -900,7 +937,7 @@ bool SourceBufferState::OnNewBuffers(
}
}
if (min_end_timestamp != kNoTimestamp)
- new_timestamp_offset += min_end_timestamp;
+ predicted_timestamp_offset += min_end_timestamp;
}
if (!frame_processor_->ProcessFrames(
@@ -910,9 +947,11 @@ bool SourceBufferState::OnNewBuffers(
}
// Only update the timestamp offset if the frame processor hasn't already.
- if (auto_update_timestamp_offset_ &&
+ if (generate_timestamps_flag() &&
timestamp_offset_before_processing == *timestamp_offset_during_append_) {
- *timestamp_offset_during_append_ = new_timestamp_offset;
+ // TODO(wolenetz): This prediction assumes the last frame in each track
+ // isn't dropped by append window trimming. See https://crbug.com/850316.
+ *timestamp_offset_during_append_ = predicted_timestamp_offset;
}
return true;
@@ -927,10 +966,15 @@ void SourceBufferState::OnEncryptedMediaInitData(
void SourceBufferState::OnSourceInitDone(
const StreamParser::InitParameters& params) {
- DCHECK_EQ(state_, PENDING_PARSER_INIT);
+ // We've either yet-to-run |init_cb_| if pending init, or we've previously
+ // run it if pending reinit.
+ DCHECK((!init_cb_.is_null() && state_ == PENDING_PARSER_INIT) ||
+ (init_cb_.is_null() && state_ == PENDING_PARSER_REINIT));
+ State old_state = state_;
state_ = PARSER_INITIALIZED;
- auto_update_timestamp_offset_ = params.auto_update_timestamp_offset;
- base::ResetAndReturn(&init_cb_).Run(params);
+
+ if (old_state == PENDING_PARSER_INIT)
+ std::move(init_cb_).Run(params);
}
} // namespace media
diff --git a/chromium/media/filters/source_buffer_state.h b/chromium/media/filters/source_buffer_state.h
index c487344eecd..7bac0c5616d 100644
--- a/chromium/media/filters/source_buffer_state.h
+++ b/chromium/media/filters/source_buffer_state.h
@@ -44,12 +44,18 @@ class MEDIA_EXPORT SourceBufferState {
~SourceBufferState();
- void Init(const StreamParser::InitCB& init_cb,
+ void Init(StreamParser::InitCB init_cb,
const std::string& expected_codecs,
const StreamParser::EncryptedMediaInitDataCB&
encrypted_media_init_data_cb,
const NewTextTrackCB& new_text_track_cb);
+ // Reconfigures this source buffer to use |new_stream_parser|. Caller must
+ // first ensure that ResetParserState() was done to flush any pending frames
+ // from the old stream parser.
+ void ChangeType(std::unique_ptr<StreamParser> new_stream_parser,
+ const std::string& new_expected_codecs);
+
// Appends new data to the StreamParser.
// Returns true if the data was successfully appended. Returns false if an
// error occurred. |*timestamp_offset| is used and possibly updated by the
@@ -91,6 +97,12 @@ class MEDIA_EXPORT SourceBufferState {
// Returns true if currently parsing a media segment, or false otherwise.
bool parsing_media_segment() const { return parsing_media_segment_; }
+ // Returns the 'Generate Timestamps Flag' for this SourceBuffer's byte stream
+ // format parser as described in the MSE Byte Stream Format Registry.
+ bool generate_timestamps_flag() const {
+ return stream_parser_->GetGenerateTimestampsFlag();
+ }
+
// Sets |frame_processor_|'s sequence mode to |sequence_mode|.
void SetSequenceMode(bool sequence_mode);
@@ -139,16 +151,30 @@ class MEDIA_EXPORT SourceBufferState {
const SourceBufferParseWarningCB& parse_warning_cb);
private:
- // State advances through this list. The intent is to ensure at least one
- // config is received prior to parser calling initialization callback, and
- // that such initialization callback occurs at most once per parser.
+ // State advances through this list to PARSER_INITIALIZED.
+ // The intent is to ensure at least one config is received prior to parser
+ // calling initialization callback, and that such initialization callback
+ // occurs at most once per parser.
+ // PENDING_PARSER_RECONFIG occurs if State had reached PARSER_INITIALIZED
+ // before changing to a new StreamParser in ChangeType(). In such case, State
+ // would then advance to PENDING_PARSER_REINIT, then PARSER_INITIALIZED upon
+ // the next initialization segment parsed, but would not run the
+ // initialization callback in this case (since such would already have
+ // occurred on the initial transition from PENDING_PARSER_INIT to
+ // PARSER_INITIALIZED.)
enum State {
UNINITIALIZED = 0,
PENDING_PARSER_CONFIG,
PENDING_PARSER_INIT,
- PARSER_INITIALIZED
+ PARSER_INITIALIZED,
+ PENDING_PARSER_RECONFIG,
+ PENDING_PARSER_REINIT
};
+ // Initializes |stream_parser_|. Also, updates |expected_audio_codecs| and
+ // |expected_video_codecs|.
+ void InitializeParser(const std::string& expected_codecs);
+
// Called by the |stream_parser_| when a new initialization segment is
// encountered.
// Returns true on a successful call. Returns false if an error occurred while
@@ -237,12 +263,6 @@ class MEDIA_EXPORT SourceBufferState {
std::vector<AudioCodec> expected_audio_codecs_;
std::vector<VideoCodec> expected_video_codecs_;
- // Indicates that timestampOffset should be updated automatically during
- // OnNewBuffers() based on the earliest end timestamp of the buffers provided.
- // TODO(wolenetz): Refactor this function while integrating April 29, 2014
- // changes to MSE spec. See http://crbug.com/371499.
- bool auto_update_timestamp_offset_;
-
DISALLOW_COPY_AND_ASSIGN(SourceBufferState);
};
diff --git a/chromium/media/filters/source_buffer_state_unittest.cc b/chromium/media/filters/source_buffer_state_unittest.cc
index caa4dd25c19..8448fef6970 100644
--- a/chromium/media/filters/source_buffer_state_unittest.cc
+++ b/chromium/media/filters/source_buffer_state_unittest.cc
@@ -78,13 +78,20 @@ class SourceBufferStateTest
std::unique_ptr<SourceBufferState> CreateAndInitSourceBufferState(
const std::string& expected_codecs) {
std::unique_ptr<SourceBufferState> sbs = CreateSourceBufferState();
+ // Instead of using SaveArg<> to update |new_config_cb_| when mocked Init is
+ // called, we use a lambda because SaveArg<> doesn't work if any of the
+ // mocked method's arguments are move-only type.
EXPECT_CALL(*mock_stream_parser_, Init(_, _, _, _, _, _, _, _))
- .WillOnce(SaveArg<1>(&new_config_cb_));
- sbs->Init(base::Bind(&SourceBufferStateTest::SourceInitDone,
- base::Unretained(this)),
+ .WillOnce([&](auto init_cb, auto config_cb, auto new_buffers_cb,
+ auto ignore_text_track, auto encrypted_media_init_data_cb,
+ auto new_segment_cb, auto end_of_segment_cb,
+ auto media_log) { new_config_cb_ = config_cb; });
+ sbs->Init(base::BindOnce(&SourceBufferStateTest::SourceInitDone,
+ base::Unretained(this)),
expected_codecs,
- base::Bind(&SourceBufferStateTest::StreamParserEncryptedInitData,
- base::Unretained(this)),
+ base::BindRepeating(
+ &SourceBufferStateTest::StreamParserEncryptedInitData,
+ base::Unretained(this)),
base::Bind(&SourceBufferStateTest::StreamParserNewTextTrack,
base::Unretained(this)));
diff --git a/chromium/media/filters/source_buffer_stream.cc b/chromium/media/filters/source_buffer_stream.cc
index ec616d4b0a5..8b0173117cf 100644
--- a/chromium/media/filters/source_buffer_stream.cc
+++ b/chromium/media/filters/source_buffer_stream.cc
@@ -147,7 +147,7 @@ std::string BufferQueueBuffersToLogString(
for (const auto& buf : buffers) {
result << "\tdts=" << buf->GetDecodeTimestamp().InMicroseconds() << " "
<< buf->AsHumanReadableString()
- << ", duration_type=" << static_cast<int>(buf->duration_type())
+ << ", is_duration_estimated=" << buf->is_duration_estimated()
<< "\n";
}
@@ -1250,7 +1250,7 @@ void SourceBufferStream<RangeClass>::TrimSpliceOverlap(
" (bad content) at time "
<< splice_timestamp.InMicroseconds();
- MEDIA_LOG(ERROR, media_log_)
+ MEDIA_LOG(WARNING, media_log_)
<< "Media is badly muxed. Detected " << overlapped_buffers.size()
<< " overlapping audio buffers at time "
<< splice_timestamp.InMicroseconds();
@@ -1267,6 +1267,16 @@ void SourceBufferStream<RangeClass>::TrimSpliceOverlap(
return;
}
+ // Trimming a buffer with estimated duration is too risky. Estimates are rough
+ // and what appears to be overlap may really just be a bad estimate. Imprecise
+ // trimming may lead to loss of AV sync.
+ if (overlapped_buffer->is_duration_estimated()) {
+ DVLOG(3) << __func__ << " Skipping audio splice trimming at PTS="
+ << splice_timestamp.InMicroseconds() << ". Overlapped buffer has "
+ << "estimated duration.";
+ return;
+ }
+
// Determine the duration of overlap.
base::TimeDelta overlapped_end_time =
overlapped_buffer->timestamp() + overlapped_buffer->duration();
@@ -1290,14 +1300,6 @@ void SourceBufferStream<RangeClass>::TrimSpliceOverlap(
return;
}
- // At this point, trimming will go ahead. Log UMAs about the type of duration
- // in the original overlapped buffer. The hope is that splicing on
- // rough-estimated durations is rare enough that we can disable it outright.
- // This would allow more liberal estimates of audio durations.
- UMA_HISTOGRAM_ENUMERATION(
- "Media.MSE.AudioSpliceDurationType", overlapped_buffer->duration_type(),
- static_cast<int>(DurationType::kDurationTypeMax) + 1);
-
// Trim overlap from the existing buffer.
DecoderBuffer::DiscardPadding discard_padding =
overlapped_buffer->discard_padding();
@@ -1974,13 +1976,21 @@ base::TimeDelta SourceBufferStream<RangeClass>::GetMaxInterbufferDistance()
template <typename RangeClass>
bool SourceBufferStream<RangeClass>::UpdateAudioConfig(
- const AudioDecoderConfig& config) {
+ const AudioDecoderConfig& config,
+ bool allow_codec_change) {
DCHECK(!audio_configs_.empty());
DCHECK(video_configs_.empty());
DVLOG(3) << "UpdateAudioConfig.";
- if (audio_configs_[0].codec() != config.codec()) {
- MEDIA_LOG(ERROR, media_log_) << "Audio codec changes not allowed.";
+ if (!allow_codec_change &&
+ audio_configs_[append_config_index_].codec() != config.codec()) {
+ // TODO(wolenetz): When we relax addSourceBuffer() and changeType() codec
+ // strictness, codec changes should be allowed even without changing the
+ // bytestream.
+ // TODO(wolenetz): Remove "experimental" from this error message when
+ // changeType() ships without needing experimental blink flag.
+ MEDIA_LOG(ERROR, media_log_) << "Audio codec changes not allowed unless "
+ "using experimental changeType().";
return false;
}
@@ -2002,13 +2012,21 @@ bool SourceBufferStream<RangeClass>::UpdateAudioConfig(
template <typename RangeClass>
bool SourceBufferStream<RangeClass>::UpdateVideoConfig(
- const VideoDecoderConfig& config) {
+ const VideoDecoderConfig& config,
+ bool allow_codec_change) {
DCHECK(!video_configs_.empty());
DCHECK(audio_configs_.empty());
DVLOG(3) << "UpdateVideoConfig.";
- if (video_configs_[0].codec() != config.codec()) {
- MEDIA_LOG(ERROR, media_log_) << "Video codec changes not allowed.";
+ if (!allow_codec_change &&
+ video_configs_[append_config_index_].codec() != config.codec()) {
+ // TODO(wolenetz): When we relax addSourceBuffer() and changeType() codec
+ // strictness, codec changes should be allowed even without changing the
+ // bytestream.
+ // TODO(wolenetz): Remove "experimental" from this error message when
+ // changeType() ships without needing experimental blink flag.
+ MEDIA_LOG(ERROR, media_log_) << "Video codec changes not allowed unless "
+ "using experimental changeType()";
return false;
}
diff --git a/chromium/media/filters/source_buffer_stream.h b/chromium/media/filters/source_buffer_stream.h
index a50e7c36df4..590d88d85cb 100644
--- a/chromium/media/filters/source_buffer_stream.h
+++ b/chromium/media/filters/source_buffer_stream.h
@@ -164,11 +164,17 @@ class MEDIA_EXPORT SourceBufferStream {
// Notifies this object that the audio config has changed and buffers in
// future Append() calls should be associated with this new config.
- bool UpdateAudioConfig(const AudioDecoderConfig& config);
+ // If the codec is allowed to change, the caller should set
+ // |allow_codec_change| to true.
+ bool UpdateAudioConfig(const AudioDecoderConfig& config,
+ bool allow_codec_change);
// Notifies this object that the video config has changed and buffers in
// future Append() calls should be associated with this new config.
- bool UpdateVideoConfig(const VideoDecoderConfig& config);
+ // If the codec is allowed to change, the caller should set
+ // |allow_codec_change| to true.
+ bool UpdateVideoConfig(const VideoDecoderConfig& config,
+ bool allow_codec_change);
// Returns the largest distance between two adjacent buffers in this stream,
// or an estimate if no two adjacent buffers have been appended to the stream
diff --git a/chromium/media/filters/source_buffer_stream_unittest.cc b/chromium/media/filters/source_buffer_stream_unittest.cc
index 83ec07e9820..9b57c0a5808 100644
--- a/chromium/media/filters/source_buffer_stream_unittest.cc
+++ b/chromium/media/filters/source_buffer_stream_unittest.cc
@@ -721,7 +721,7 @@ class SourceBufferStreamTest : public testing::TestWithParam<BufferingApi> {
&kDataA, kDataSize, is_keyframe, GetStreamType(), 0);
buffer->set_timestamp(buffer_timestamps[0]);
if (is_duration_estimated)
- buffer->set_duration_type(DurationType::kRoughEstimate);
+ buffer->set_is_duration_estimated(true);
if (buffer_timestamps[1] != buffer_timestamps[0]) {
buffer->SetDecodeTimestamp(
@@ -3472,7 +3472,7 @@ TEST_P(SourceBufferStreamTest, ConfigChange_Basic) {
CheckVideoConfig(video_config_);
// Signal a config change.
- STREAM_OP(UpdateVideoConfig(new_config));
+ STREAM_OP(UpdateVideoConfig(new_config, false));
// Make sure updating the config doesn't change anything since new_config
// should not be associated with the buffer GetNextBuffer() will return.
@@ -3508,7 +3508,7 @@ TEST_P(SourceBufferStreamTest, ConfigChange_Seek) {
Seek(0);
NewCodedFrameGroupAppend(0, 5, &kDataA);
- STREAM_OP(UpdateVideoConfig(new_config));
+ STREAM_OP(UpdateVideoConfig(new_config, false));
NewCodedFrameGroupAppend(5, 5, &kDataB);
// Seek to the start of the buffers with the new config and make sure a
@@ -4545,6 +4545,27 @@ TEST_P(SourceBufferStreamTest, Audio_NoSpliceForBadOverlap) {
CheckNoNextBuffer();
}
+TEST_P(SourceBufferStreamTest, Audio_NoSpliceForEstimatedDuration) {
+ SetAudioStream();
+ Seek(0);
+
+ // Append two buffers, the latter having estimated duration.
+ NewCodedFrameGroupAppend("0D10K 10D10EK");
+ CheckExpectedRangesByTimestamp("{ [0,20) }");
+ CheckExpectedBuffers("0D10K 10D10EK");
+ CheckNoNextBuffer();
+
+ Seek(0);
+
+ // Add a new frame in a separate coded frame group that falls in the middle of
+ // the second buffer. In spite of the overlap, no splice should be performed
+ // due to the overlapped buffer having estimated duration.
+ NewCodedFrameGroupAppend("15D10K");
+ CheckExpectedRangesByTimestamp("{ [0,25) }");
+ CheckExpectedBuffers("0D10K 10D10EK 15D10K");
+ CheckNoNextBuffer();
+}
+
TEST_P(SourceBufferStreamTest, Audio_SpliceTrimming_ExistingTrimming) {
const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(4);
const base::TimeDelta kNoDiscard = base::TimeDelta();
@@ -4688,7 +4709,7 @@ TEST_P(SourceBufferStreamTest, Audio_ConfigChangeWithPreroll) {
NewCodedFrameGroupAppend("0K 3K 6K");
// Update the configuration.
- STREAM_OP(UpdateAudioConfig(new_config));
+ STREAM_OP(UpdateAudioConfig(new_config, false));
// We haven't read any buffers at this point, so the config for the next
// buffer at time 0 should still be the original config.
@@ -4948,7 +4969,7 @@ TEST_P(SourceBufferStreamTest, ConfigChange_ReSeek) {
// Append a few buffers, with a config change in the middle.
VideoDecoderConfig new_config = TestVideoConfig::Large();
NewCodedFrameGroupAppend("2000K 2010 2020D10");
- STREAM_OP(UpdateVideoConfig(new_config));
+ STREAM_OP(UpdateVideoConfig(new_config, false));
NewCodedFrameGroupAppend("2030K 2040 2050D10");
CheckExpectedRangesByTimestamp("{ [2000,2060) }");
diff --git a/chromium/media/filters/stream_parser_factory.cc b/chromium/media/filters/stream_parser_factory.cc
index 8b9ff97eab9..d515e2b0ce7 100644
--- a/chromium/media/filters/stream_parser_factory.cc
+++ b/chromium/media/filters/stream_parser_factory.cc
@@ -16,6 +16,7 @@
#include "build/build_config.h"
#include "media/base/media.h"
#include "media/base/media_switches.h"
+#include "media/base/video_codecs.h"
#include "media/formats/mp4/mp4_stream_parser.h"
#include "media/formats/mpeg/adts_stream_parser.h"
#include "media/formats/mpeg/mpeg1_audio_stream_parser.h"
@@ -92,9 +93,8 @@ static const CodecInfo kOpusCodecInfo = {"opus", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_OPUS};
#if BUILDFLAG(ENABLE_AV1_DECODER)
-// TODO(dalecurtis): This is not the correct final string. Fix before enabling
-// by default. http://crbug.com/784607
-static const CodecInfo kAV1CodecInfo = {"av1", CodecInfo::VIDEO, nullptr,
+// Note: Validation of the codec string is handled by the caller.
+static const CodecInfo kAV1CodecInfo = {"av01.*", CodecInfo::VIDEO, nullptr,
CodecInfo::HISTOGRAM_AV1};
#endif
diff --git a/chromium/media/filters/video_frame_stream_unittest.cc b/chromium/media/filters/video_frame_stream_unittest.cc
index 6c3f7f3006f..ee116463f87 100644
--- a/chromium/media/filters/video_frame_stream_unittest.cc
+++ b/chromium/media/filters/video_frame_stream_unittest.cc
@@ -85,8 +85,8 @@ class VideoFrameStreamTest
video_frame_stream_.reset(new VideoFrameStream(
std::make_unique<VideoFrameStream::StreamTraits>(&media_log_),
message_loop_.task_runner(),
- base::Bind(&VideoFrameStreamTest::CreateVideoDecodersForTest,
- base::Unretained(this)),
+ base::BindRepeating(&VideoFrameStreamTest::CreateVideoDecodersForTest,
+ base::Unretained(this)),
&media_log_));
video_frame_stream_->set_decoder_change_observer_for_testing(base::Bind(
&VideoFrameStreamTest::OnDecoderChanged, base::Unretained(this)));
@@ -259,12 +259,14 @@ class VideoFrameStreamTest
void Initialize() {
pending_initialize_ = true;
video_frame_stream_->Initialize(
- demuxer_stream_.get(), base::Bind(&VideoFrameStreamTest::OnInitialized,
- base::Unretained(this)),
+ demuxer_stream_.get(),
+ base::BindOnce(&VideoFrameStreamTest::OnInitialized,
+ base::Unretained(this)),
cdm_context_.get(),
- base::Bind(&VideoFrameStreamTest::OnStatistics, base::Unretained(this)),
- base::Bind(&VideoFrameStreamTest::OnWaitingForDecryptionKey,
- base::Unretained(this)));
+ base::BindRepeating(&VideoFrameStreamTest::OnStatistics,
+ base::Unretained(this)),
+ base::BindRepeating(&VideoFrameStreamTest::OnWaitingForDecryptionKey,
+ base::Unretained(this)));
base::RunLoop().RunUntilIdle();
}
diff --git a/chromium/media/filters/video_renderer_algorithm.cc b/chromium/media/filters/video_renderer_algorithm.cc
index aa98ee6cc22..68847a95d14 100644
--- a/chromium/media/filters/video_renderer_algorithm.cc
+++ b/chromium/media/filters/video_renderer_algorithm.cc
@@ -165,14 +165,22 @@ scoped_refptr<VideoFrame> VideoRendererAlgorithm::Render(
}
// Step 7: Drop frames which occur prior to the frame to be rendered. If any
- // frame has a zero render count it should be reported as dropped.
+ // frame unexpectedly has a zero render count it should be reported as
+ // dropped. When using cadence some frames may be expected to be skipped and
+ // should not be counted as dropped.
if (frame_to_render > 0) {
if (frames_dropped) {
for (int i = 0; i < frame_to_render; ++i) {
const ReadyFrame& frame = frame_queue_[i];
+
+ // If a frame was ever rendered, don't count it as dropped.
if (frame.render_count != frame.drop_count)
continue;
+ // If we expected to never render the frame, don't count it as dropped.
+ if (cadence_estimator_.has_cadence() && !frame.ideal_render_count)
+ continue;
+
// If frame dropping is disabled, ignore the results of the algorithm
// and return the earliest unrendered frame.
if (frame_dropping_disabled_) {
diff --git a/chromium/media/filters/video_renderer_algorithm_unittest.cc b/chromium/media/filters/video_renderer_algorithm_unittest.cc
index ec93d0ec9a9..1dc9e1f34e8 100644
--- a/chromium/media/filters/video_renderer_algorithm_unittest.cc
+++ b/chromium/media/filters/video_renderer_algorithm_unittest.cc
@@ -1122,22 +1122,15 @@ TEST_F(VideoRendererAlgorithmTest, BestFrameByFractionalCadence) {
TickGenerator frame_tg(base::TimeTicks(), test_rate[0]);
TickGenerator display_tg(tick_clock_->NowTicks(), test_rate[1]);
- const size_t desired_drop_pattern = test_rate[0] / test_rate[1] - 1;
scoped_refptr<VideoFrame> current_frame;
RunFramePumpTest(
true, &frame_tg, &display_tg,
- [&current_frame, desired_drop_pattern, this](
- const scoped_refptr<VideoFrame>& frame, size_t frames_dropped) {
+ [&current_frame, this](const scoped_refptr<VideoFrame>& frame,
+ size_t frames_dropped) {
ASSERT_TRUE(frame);
- // The first frame should have zero dropped frames, but each Render()
- // call after should drop the same number of frames based on the
- // fractional cadence.
- if (!current_frame)
- ASSERT_EQ(0u, frames_dropped);
- else
- ASSERT_EQ(desired_drop_pattern, frames_dropped);
-
+ // We don't count frames dropped that cadence says we should skip.
+ ASSERT_EQ(0u, frames_dropped);
ASSERT_NE(current_frame, frame);
ASSERT_TRUE(is_using_cadence());
current_frame = frame;
diff --git a/chromium/media/filters/vpx_video_decoder_unittest.cc b/chromium/media/filters/vpx_video_decoder_unittest.cc
index 273687d27a3..611b6cc86b9 100644
--- a/chromium/media/filters/vpx_video_decoder_unittest.cc
+++ b/chromium/media/filters/vpx_video_decoder_unittest.cc
@@ -297,7 +297,9 @@ TEST_F(VpxVideoDecoderTest, FrameValidAfterPoolDestruction) {
}
// The test stream uses profile 2, which needs high bit depth support in libvpx.
-#if !defined(LIBVPX_NO_HIGH_BIT_DEPTH)
+// On ARM we fail to decode the final, duplicate frame, so there is no point in
+// running this test (https://crbug.com/864458).
+#if !defined(LIBVPX_NO_HIGH_BIT_DEPTH) && !defined(ARCH_CPU_ARM_FAMILY)
TEST_F(VpxVideoDecoderTest, MemoryPoolAllowsMultipleDisplay) {
// Initialize with dummy data, we could read it from the test clip, but it's
// not necessary for this test.
@@ -309,36 +311,27 @@ TEST_F(VpxVideoDecoderTest, MemoryPoolAllowsMultipleDisplay) {
FFmpegGlue glue(&protocol);
ASSERT_TRUE(glue.OpenContext());
- AVPacket packet;
+ AVPacket packet = {};
while (av_read_frame(glue.format_context(), &packet) >= 0) {
- if (Decode(DecoderBuffer::CopyFrom(packet.data, packet.size)) !=
- DecodeStatus::OK) {
- av_packet_unref(&packet);
- break;
- }
+ DecodeStatus decode_status =
+ Decode(DecoderBuffer::CopyFrom(packet.data, packet.size));
av_packet_unref(&packet);
+ if (decode_status != DecodeStatus::OK)
+ break;
}
- // Android returns 25 frames while other platforms return 26 for some reason;
- // we don't really care about the exact number.
- ASSERT_GE(output_frames_.size(), 25u);
-
- scoped_refptr<VideoFrame> last_frame = output_frames_.back();
+ ASSERT_EQ(output_frames_.size(), 26u);
- // Duplicate frame is actually two before the last in this bitstream.
- scoped_refptr<VideoFrame> dupe_frame =
- output_frames_[output_frames_.size() - 3];
+ // The final frame is a duplicate of the third-from-final one.
+ scoped_refptr<VideoFrame> last_frame = output_frames_[25];
+ scoped_refptr<VideoFrame> dupe_frame = output_frames_[23];
-#if !defined(OS_ANDROID)
- // Android doesn't seem to expose this bug, but the rest of the test is still
- // reasonable to complete even on Android.
EXPECT_EQ(last_frame->data(VideoFrame::kYPlane),
dupe_frame->data(VideoFrame::kYPlane));
EXPECT_EQ(last_frame->data(VideoFrame::kUPlane),
dupe_frame->data(VideoFrame::kUPlane));
EXPECT_EQ(last_frame->data(VideoFrame::kVPlane),
dupe_frame->data(VideoFrame::kVPlane));
-#endif
// This will release all frames held by the memory pool, but should not
// release |last_frame| since we still have a ref despite sharing the same
@@ -351,6 +344,6 @@ TEST_F(VpxVideoDecoderTest, MemoryPoolAllowsMultipleDisplay) {
memset(last_frame->data(VideoFrame::kYPlane), 0,
last_frame->row_bytes(VideoFrame::kYPlane));
}
-#endif // !defined(LIBVPX_NO_HIGH_BIT_DEPTH)
+#endif // !defined(LIBVPX_NO_HIGH_BIT_DEPTH) && !defined(ARCH_CPU_ARM_FAMILY)
} // namespace media