summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorservolk <servolk@chromium.org>2016-03-01 14:44:40 -0800
committerCommit bot <commit-bot@chromium.org>2016-03-01 22:45:50 +0000
commit95dc4ad373d2aef14c9b439397f1a4599b64bd6a (patch)
tree2bf83218726f46bf4a18bae45756155f76c3946b /media
parent45e15292b538db8e1b60f4e0eeea1c0587e3c190 (diff)
downloadchromium_src-95dc4ad373d2aef14c9b439397f1a4599b64bd6a.zip
chromium_src-95dc4ad373d2aef14c9b439397f1a4599b64bd6a.tar.gz
chromium_src-95dc4ad373d2aef14c9b439397f1a4599b64bd6a.tar.bz2
Basic media tracks implementation for media stream parsers
This CL adds basic media::MediaTrack implementation, media::MediaTracks collection that associates media tracks with audio/video configs, and makes necessary changes in MSE stream parsers to pass around the MediaTracks collection instead of individual audio/video configs. BUG=249427, 249428 Review URL: https://codereview.chromium.org/1716503002 Cr-Commit-Position: refs/heads/master@{#378583}
Diffstat (limited to 'media')
-rw-r--r--media/base/BUILD.gn4
-rw-r--r--media/base/media_track.cc18
-rw-r--r--media/base/media_track.h41
-rw-r--r--media/base/media_tracks.cc81
-rw-r--r--media/base/media_tracks.h62
-rw-r--r--media/base/stream_parser.h20
-rw-r--r--media/blink/websourcebuffer_impl.cc5
-rw-r--r--media/blink/websourcebuffer_impl.h3
-rw-r--r--media/filters/chunk_demuxer_unittest.cc45
-rw-r--r--media/filters/media_source_state.cc12
-rw-r--r--media/filters/media_source_state.h7
-rw-r--r--media/formats/common/stream_parser_test_base.cc15
-rw-r--r--media/formats/common/stream_parser_test_base.h3
-rw-r--r--media/formats/mp2t/mp2t_stream_parser.cc28
-rw-r--r--media/formats/mp2t/mp2t_stream_parser_unittest.cc10
-rw-r--r--media/formats/mp4/mp4_stream_parser.cc12
-rw-r--r--media/formats/mp4/mp4_stream_parser_unittest.cc14
-rw-r--r--media/formats/mpeg/mpeg_audio_stream_parser_base.cc8
-rw-r--r--media/formats/webm/webm_stream_parser.cc15
-rw-r--r--media/media.gyp4
-rw-r--r--media/test/pipeline_integration_test.cc7
21 files changed, 340 insertions, 74 deletions
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn
index 0e4bebc..6d37637 100644
--- a/media/base/BUILD.gn
+++ b/media/base/BUILD.gn
@@ -135,6 +135,10 @@ source_set("base") {
"media_resources.h",
"media_switches.cc",
"media_switches.h",
+ "media_track.cc",
+ "media_track.h",
+ "media_tracks.cc",
+ "media_tracks.h",
"media_util.cc",
"media_util.h",
"mime_util.cc",
diff --git a/media/base/media_track.cc b/media/base/media_track.cc
new file mode 100644
index 0000000..ad5178f
--- /dev/null
+++ b/media/base/media_track.cc
@@ -0,0 +1,18 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/media_track.h"
+
+namespace media {
+
+MediaTrack::MediaTrack(Type type,
+ const std::string& id,
+ const std::string& kind,
+ const std::string& label,
+ const std::string& lang)
+ : type_(type), id_(id), kind_(kind), label_(label), language_(lang) {}
+
+MediaTrack::~MediaTrack() {}
+
+} // namespace media
diff --git a/media/base/media_track.h b/media/base/media_track.h
new file mode 100644
index 0000000..a5cb6d3
--- /dev/null
+++ b/media/base/media_track.h
@@ -0,0 +1,41 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_MEDIA_TRACK_H_
+#define MEDIA_BASE_MEDIA_TRACK_H_
+
+#include <string>
+
+#include "media/base/media_export.h"
+
+namespace media {
+
+class MEDIA_EXPORT MediaTrack {
+ public:
+ enum Type { Text, Audio, Video };
+ MediaTrack(Type type,
+ const std::string& id,
+ const std::string& kind,
+ const std::string& label,
+ const std::string& lang);
+ ~MediaTrack();
+
+ Type type() const { return type_; }
+
+ const std::string& id() const { return id_; }
+ const std::string& kind() const { return kind_; }
+ const std::string& label() const { return label_; }
+ const std::string& language() const { return language_; }
+
+ private:
+ Type type_;
+ std::string id_;
+ std::string kind_;
+ std::string label_;
+ std::string language_;
+};
+
+} // namespace media
+
+#endif // MEDIA_BASE_MEDIA_TRACK_H_
diff --git a/media/base/media_tracks.cc b/media/base/media_tracks.cc
new file mode 100644
index 0000000..832e5a8
--- /dev/null
+++ b/media/base/media_tracks.cc
@@ -0,0 +1,81 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/media_tracks.h"
+
+#include "base/bind.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/video_decoder_config.h"
+
+namespace media {
+
+MediaTracks::MediaTracks() {}
+
+MediaTracks::~MediaTracks() {}
+
+void MediaTracks::AddAudioTrack(const AudioDecoderConfig& config,
+ const std::string& id,
+ const std::string& kind,
+ const std::string& label,
+ const std::string& language) {
+ DCHECK(config.IsValidConfig());
+ CHECK(audio_configs_.find(id) == audio_configs_.end());
+ scoped_ptr<MediaTrack> track = make_scoped_ptr(
+ new MediaTrack(MediaTrack::Audio, id, kind, label, language));
+ tracks_.push_back(std::move(track));
+ audio_configs_[id] = config;
+}
+
+void MediaTracks::AddVideoTrack(const VideoDecoderConfig& config,
+ const std::string& id,
+ const std::string& kind,
+ const std::string& label,
+ const std::string& language) {
+ DCHECK(config.IsValidConfig());
+ CHECK(video_configs_.find(id) == video_configs_.end());
+ scoped_ptr<MediaTrack> track = make_scoped_ptr(
+ new MediaTrack(MediaTrack::Video, id, kind, label, language));
+ tracks_.push_back(std::move(track));
+ video_configs_[id] = config;
+}
+
+const AudioDecoderConfig& MediaTracks::getAudioConfig(
+ const std::string& id) const {
+ auto it = audio_configs_.find(id);
+ if (it != audio_configs_.end())
+ return it->second;
+ static AudioDecoderConfig invalidConfig;
+ return invalidConfig;
+}
+
+const VideoDecoderConfig& MediaTracks::getVideoConfig(
+ const std::string& id) const {
+ auto it = video_configs_.find(id);
+ if (it != video_configs_.end())
+ return it->second;
+ static VideoDecoderConfig invalidConfig;
+ return invalidConfig;
+}
+
+const AudioDecoderConfig& MediaTracks::getFirstAudioConfig() const {
+ for (const auto& track : tracks()) {
+ if (track->type() == MediaTrack::Audio) {
+ return getAudioConfig(track->id());
+ }
+ }
+ static AudioDecoderConfig invalidConfig;
+ return invalidConfig;
+}
+
+const VideoDecoderConfig& MediaTracks::getFirstVideoConfig() const {
+ for (const auto& track : tracks()) {
+ if (track->type() == MediaTrack::Video) {
+ return getVideoConfig(track->id());
+ }
+ }
+ static VideoDecoderConfig invalidConfig;
+ return invalidConfig;
+}
+
+} // namespace media
diff --git a/media/base/media_tracks.h b/media/base/media_tracks.h
new file mode 100644
index 0000000..4e0fbb0
--- /dev/null
+++ b/media/base/media_tracks.h
@@ -0,0 +1,62 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_MEDIA_TRACKS_H_
+#define MEDIA_BASE_MEDIA_TRACKS_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "media/base/media_export.h"
+#include "media/base/media_track.h"
+
+namespace media {
+
+class AudioDecoderConfig;
+class VideoDecoderConfig;
+
+class MEDIA_EXPORT MediaTracks {
+ public:
+ typedef std::vector<scoped_ptr<MediaTrack>> MediaTracksCollection;
+
+ MediaTracks();
+ ~MediaTracks();
+
+ // Callers need to ensure that track id is unique.
+ void AddAudioTrack(const AudioDecoderConfig& config,
+ const std::string& id,
+ const std::string& kind,
+ const std::string& label,
+ const std::string& language);
+ // Callers need to ensure that track id is unique.
+ void AddVideoTrack(const VideoDecoderConfig& config,
+ const std::string& id,
+ const std::string& kind,
+ const std::string& label,
+ const std::string& language);
+
+ const MediaTracksCollection& tracks() const { return tracks_; }
+
+ const AudioDecoderConfig& getAudioConfig(const std::string& id) const;
+ const VideoDecoderConfig& getVideoConfig(const std::string& id) const;
+
+ // TODO(servolk): These are temporary helpers useful until all code paths are
+ // converted to properly handle multiple media tracks.
+ const AudioDecoderConfig& getFirstAudioConfig() const;
+ const VideoDecoderConfig& getFirstVideoConfig() const;
+
+ private:
+ MediaTracksCollection tracks_;
+ std::map<std::string, AudioDecoderConfig> audio_configs_;
+ std::map<std::string, VideoDecoderConfig> video_configs_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaTracks);
+};
+
+} // namespace media
+
+#endif // MEDIA_BASE_MEDIA_TRACKS_H_
diff --git a/media/base/stream_parser.h b/media/base/stream_parser.h
index 11740c9..4b9fa7f 100644
--- a/media/base/stream_parser.h
+++ b/media/base/stream_parser.h
@@ -25,10 +25,9 @@
namespace media {
-class AudioDecoderConfig;
+class MediaTracks;
class StreamParserBuffer;
class TextTrackConfig;
-class VideoDecoderConfig;
// Abstract interface for parsing media byte streams.
class MEDIA_EXPORT StreamParser {
@@ -76,18 +75,17 @@ class MEDIA_EXPORT StreamParser {
typedef base::Callback<void(const InitParameters& params)> InitCB;
// Indicates when new stream configurations have been parsed.
- // First parameter - The new audio configuration. If the config is not valid
- // then it means that there isn't an audio stream.
- // Second parameter - The new video configuration. If the config is not valid
- // then it means that there isn't an audio stream.
- // Third parameter - The new text tracks configuration. If the map is empty,
- // then no text tracks were parsed from the stream.
+ // First parameter - An object containing information about media tracks as
+ // well as audio/video decoder configs associated with each
+ // track.
+ // Second parameter - The new text tracks configuration. If the map is empty,
+ // then no text tracks were parsed from the stream.
// Return value - True if the new configurations are accepted.
// False if the new configurations are not supported
// and indicates that a parsing error should be signalled.
- typedef base::Callback<bool(const AudioDecoderConfig&,
- const VideoDecoderConfig&,
- const TextTrackConfigMap&)> NewConfigCB;
+ typedef base::Callback<bool(scoped_ptr<MediaTracks>,
+ const TextTrackConfigMap&)>
+ NewConfigCB;
// New stream buffers have been parsed.
// First parameter - A queue of newly parsed audio buffers.
diff --git a/media/blink/websourcebuffer_impl.cc b/media/blink/websourcebuffer_impl.cc
index ffb62c5..ea09bde 100644
--- a/media/blink/websourcebuffer_impl.cc
+++ b/media/blink/websourcebuffer_impl.cc
@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
+#include "media/base/media_tracks.h"
#include "media/base/timestamp_constants.h"
#include "media/filters/chunk_demuxer.h"
#include "third_party/WebKit/public/platform/WebSourceBufferClient.h"
@@ -158,8 +159,10 @@ void WebSourceBufferImpl::removedFromMediaSource() {
client_ = NULL;
}
-void WebSourceBufferImpl::InitSegmentReceived() {
+void WebSourceBufferImpl::InitSegmentReceived(const MediaTracks& tracks) {
DVLOG(1) << __FUNCTION__;
+ // TODO(servolk): Implement passing MediaTrack info to blink level.
+ // https://crbug.com/249428
client_->initializationSegmentReceived();
}
diff --git a/media/blink/websourcebuffer_impl.h b/media/blink/websourcebuffer_impl.h
index 9111fd2..1dc54e6 100644
--- a/media/blink/websourcebuffer_impl.h
+++ b/media/blink/websourcebuffer_impl.h
@@ -16,6 +16,7 @@
namespace media {
class ChunkDemuxer;
+class MediaTracks;
class WebSourceBufferImpl : public blink::WebSourceBuffer {
public:
@@ -42,7 +43,7 @@ class WebSourceBufferImpl : public blink::WebSourceBuffer {
private:
// Demuxer callback handler to process an initialization segment received
// during an append() call.
- void InitSegmentReceived();
+ void InitSegmentReceived(const MediaTracks& tracks);
std::string id_;
ChunkDemuxer* demuxer_; // Owned by WebMediaPlayerImpl.
diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc
index c095f5a..bd2a87e 100644
--- a/media/filters/chunk_demuxer_unittest.cc
+++ b/media/filters/chunk_demuxer_unittest.cc
@@ -18,6 +18,7 @@
#include "media/base/audio_decoder_config.h"
#include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h"
+#include "media/base/media_tracks.h"
#include "media/base/mock_demuxer_host.h"
#include "media/base/mock_media_log.h"
#include "media/base/test_data_util.h"
@@ -841,7 +842,7 @@ class ChunkDemuxerTest : public ::testing::Test {
// it.
if (stream_flags != 0) {
ExpectInitMediaLogs(stream_flags);
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
} else {
// OnNewConfigs() requires at least one audio, video, or text track.
EXPECT_MEDIA_LOG(StreamParsingFailed());
@@ -883,11 +884,11 @@ class ChunkDemuxerTest : public ::testing::Test {
// incompatible with InSequence tests. Refactoring of the duration
// set expectation to not be added during CreateInitDoneCB() could fix this.
ExpectInitMediaLogs(audio_flags);
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendInitSegmentWithSourceId(audio_id, audio_flags);
ExpectInitMediaLogs(video_flags);
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendInitSegmentWithSourceId(video_id, video_flags);
return true;
}
@@ -923,7 +924,7 @@ class ChunkDemuxerTest : public ::testing::Test {
// Adding expectation prior to CreateInitDoneCB() here because InSequence
// tests require init segment received before duration set.
ExpectInitMediaLogs(HAS_AUDIO | HAS_VIDEO);
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
demuxer_->Initialize(
&host_, CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744),
PIPELINE_OK), true);
@@ -949,7 +950,7 @@ class ChunkDemuxerTest : public ::testing::Test {
// media/test/data/bear-320x240-manifest.js which were
// generated from media/test/data/bear-640x360.webm and
// media/test/data/bear-320x240.webm respectively.
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendData(bear2->data(), 4340);
// Append a media segment that goes from [0.527000, 1.014000).
@@ -960,7 +961,7 @@ class ChunkDemuxerTest : public ::testing::Test {
// Append initialization segment for bear1 & fill gap with [779-1197)
// segment.
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendData(bear1->data(), 4370);
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(23));
EXPECT_MEDIA_LOG(GeneratedSplice(26000, 779000));
@@ -1308,7 +1309,7 @@ class ChunkDemuxerTest : public ::testing::Test {
// Read a WebM file into memory and send the data to the demuxer.
scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendDataInPieces(buffer->data(), buffer->data_size(), 512);
// Verify that the timestamps on the first few packets match what we
@@ -1345,7 +1346,7 @@ class ChunkDemuxerTest : public ::testing::Test {
void(EmeInitDataType init_data_type,
const std::vector<uint8_t>& init_data));
- MOCK_METHOD0(InitSegmentReceived, void(void));
+ MOCK_METHOD1(InitSegmentReceived, void(const MediaTracks&));
void Seek(base::TimeDelta seek_time) {
demuxer_->StartWaitingForSeek(seek_time);
@@ -1547,7 +1548,7 @@ TEST_F(ChunkDemuxerTest, SingleTextTrackIdChange) {
CreateInitSegmentWithAlternateTextTrackNum(HAS_TEXT | HAS_AUDIO | HAS_VIDEO,
false, false,
&info_tracks, &info_tracks_size);
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
demuxer_->AppendData(kSourceId, info_tracks.get(), info_tracks_size,
append_window_start_for_next_append_,
append_window_end_for_next_append_,
@@ -1592,7 +1593,7 @@ TEST_F(ChunkDemuxerTest, InitSegmentSetsNeedRandomAccessPointFlag) {
MuxedStreamInfo(kTextTrackNum, "25K 40K"));
CheckExpectedRanges("{ [23,46) }");
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendInitSegment(HAS_TEXT | HAS_AUDIO | HAS_VIDEO);
AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "46K 69K", 23),
MuxedStreamInfo(kVideoTrackNum, "60 90K", 30),
@@ -1616,7 +1617,7 @@ TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppended) {
EXPECT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk);
ExpectInitMediaLogs(HAS_AUDIO);
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendInitSegmentWithSourceId("audio", HAS_AUDIO);
ShutdownDemuxer();
@@ -1635,7 +1636,7 @@ TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppendedText) {
.Times(Exactly(1));
ExpectInitMediaLogs(HAS_VIDEO);
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendInitSegmentWithSourceId("video_and_text", HAS_VIDEO | HAS_TEXT);
ShutdownDemuxer();
@@ -2157,7 +2158,7 @@ TEST_F(ChunkDemuxerTest, AppendingInPieces) {
dst += cluster_b->size();
ExpectInitMediaLogs(HAS_AUDIO | HAS_VIDEO);
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendDataInPieces(buffer.get(), buffer_size);
GenerateExpectedReads(0, 9);
@@ -2412,7 +2413,7 @@ TEST_F(ChunkDemuxerTest, MultipleHeaders) {
AppendCluster(kDefaultFirstCluster());
// Append another identical initialization segment.
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendInitSegment(HAS_AUDIO | HAS_VIDEO);
AppendCluster(kDefaultSecondCluster());
@@ -2468,7 +2469,7 @@ TEST_F(ChunkDemuxerTest, AddIdFailures) {
ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit);
ExpectInitMediaLogs(HAS_AUDIO);
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendInitSegmentWithSourceId(audio_id, HAS_AUDIO);
// Adding an id after append should fail.
@@ -2712,7 +2713,7 @@ TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioIdOnly) {
ASSERT_EQ(AddId(kSourceId, HAS_AUDIO), ChunkDemuxer::kOk);
ExpectInitMediaLogs(HAS_AUDIO);
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendInitSegment(HAS_AUDIO);
// Test a simple cluster.
@@ -2736,7 +2737,7 @@ TEST_F(ChunkDemuxerTest, GetBufferedRanges_VideoIdOnly) {
ASSERT_EQ(AddId(kSourceId, HAS_VIDEO), ChunkDemuxer::kOk);
ExpectInitMediaLogs(HAS_VIDEO);
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendInitSegment(HAS_VIDEO);
// Test a simple cluster.
@@ -3406,7 +3407,7 @@ TEST_F(ChunkDemuxerTest, EmitBuffersDuringAbort) {
// PTS: 353788 (0x000565fc) [= 90 kHz-Timestamp: 0:00:03.9309]
scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("bear-1280x720.ts");
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendData(kSourceId, buffer->data(), buffer->data_size());
// Confirm we're in the middle of parsing a media segment.
@@ -3454,7 +3455,7 @@ TEST_F(ChunkDemuxerTest, SeekCompleteDuringAbort) {
// PTS: 353788 (0x000565fc) [= 90 kHz-Timestamp: 0:00:03.9309]
scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("bear-1280x720.ts");
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
AppendData(kSourceId, buffer->data(), buffer->data_size());
// Confirm we're in the middle of parsing a media segment.
@@ -4065,7 +4066,7 @@ TEST_F(ChunkDemuxerTest, AppendWindow_WebMFile_AudioOnly) {
scoped_refptr<DecoderBuffer> buffer =
ReadTestDataFile("bear-320x240-audio-only.webm");
ExpectInitMediaLogs(HAS_AUDIO);
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(2));
AppendDataInPieces(buffer->data(), buffer->data_size(), 128);
@@ -4092,7 +4093,7 @@ TEST_F(ChunkDemuxerTest, AppendWindow_AudioConfigUpdateRemovesPreroll) {
scoped_refptr<DecoderBuffer> buffer =
ReadTestDataFile("bear-320x240-audio-only.webm");
ExpectInitMediaLogs(HAS_AUDIO);
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(2));
AppendDataInPieces(buffer->data(), buffer->data_size(), 512);
CheckExpectedRanges("{ }");
@@ -4103,7 +4104,7 @@ TEST_F(ChunkDemuxerTest, AppendWindow_AudioConfigUpdateRemovesPreroll) {
// Read a second WebM with a different config in and append the data.
scoped_refptr<DecoderBuffer> buffer2 =
ReadTestDataFile("bear-320x240-audio-only-48khz.webm");
- EXPECT_CALL(*this, InitSegmentReceived());
+ EXPECT_CALL(*this, InitSegmentReceived(_));
EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(21));
EXPECT_CALL(host_, SetDuration(_)).Times(AnyNumber());
ASSERT_TRUE(SetTimestampOffset(kSourceId, duration_1));
diff --git a/media/filters/media_source_state.cc b/media/filters/media_source_state.cc
index ede9605..8f2f87c 100644
--- a/media/filters/media_source_state.cc
+++ b/media/filters/media_source_state.cc
@@ -6,6 +6,8 @@
#include "base/callback_helpers.h"
#include "base/stl_util.h"
+#include "media/base/media_track.h"
+#include "media/base/media_tracks.h"
#include "media/filters/chunk_demuxer.h"
#include "media/filters/frame_processor.h"
#include "media/filters/source_buffer_stream.h"
@@ -468,9 +470,13 @@ bool MediaSourceState::IsSeekWaitingForData() const {
bool MediaSourceState::OnNewConfigs(
bool allow_audio,
bool allow_video,
- const AudioDecoderConfig& audio_config,
- const VideoDecoderConfig& video_config,
+ scoped_ptr<MediaTracks> tracks,
const StreamParser::TextTrackConfigMap& text_configs) {
+ DCHECK(tracks.get());
+ media_tracks_ = std::move(tracks);
+ const AudioDecoderConfig& audio_config = media_tracks_->getFirstAudioConfig();
+ const VideoDecoderConfig& video_config = media_tracks_->getFirstVideoConfig();
+
DVLOG(1) << "OnNewConfigs(" << allow_audio << ", " << allow_video << ", "
<< audio_config.IsValidConfig() << ", "
<< video_config.IsValidConfig() << ")";
@@ -638,7 +644,7 @@ bool MediaSourceState::OnNewConfigs(
DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed");
if (success)
- init_segment_received_cb_.Run();
+ init_segment_received_cb_.Run(*media_tracks_);
return success;
}
diff --git a/media/filters/media_source_state.h b/media/filters/media_source_state.h
index 1a8e42a..1197015 100644
--- a/media/filters/media_source_state.h
+++ b/media/filters/media_source_state.h
@@ -28,7 +28,7 @@ class MEDIA_EXPORT MediaSourceState {
typedef base::Callback<ChunkDemuxerStream*(DemuxerStream::Type)>
CreateDemuxerStreamCB;
- typedef base::Closure InitSegmentReceivedCB;
+ typedef base::Callback<void(const MediaTracks&)> InitSegmentReceivedCB;
typedef base::Callback<void(ChunkDemuxerStream*, const TextTrackConfig&)>
NewTextTrackCB;
@@ -124,8 +124,7 @@ class MEDIA_EXPORT MediaSourceState {
// processing decoder configurations.
bool OnNewConfigs(bool allow_audio,
bool allow_video,
- const AudioDecoderConfig& audio_config,
- const VideoDecoderConfig& video_config,
+ scoped_ptr<MediaTracks> tracks,
const StreamParser::TextTrackConfigMap& text_configs);
// Called by the |stream_parser_| at the beginning of a new media segment.
@@ -183,6 +182,8 @@ class MEDIA_EXPORT MediaSourceState {
// The object used to parse appended data.
scoped_ptr<StreamParser> stream_parser_;
+ scoped_ptr<MediaTracks> media_tracks_;
+
ChunkDemuxerStream* audio_; // Not owned by |this|.
ChunkDemuxerStream* video_; // Not owned by |this|.
diff --git a/media/formats/common/stream_parser_test_base.cc b/media/formats/common/stream_parser_test_base.cc
index de80bac..b42173f 100644
--- a/media/formats/common/stream_parser_test_base.cc
+++ b/media/formats/common/stream_parser_test_base.cc
@@ -7,6 +7,8 @@
#include <utility>
#include "base/bind.h"
+#include "media/base/media_track.h"
+#include "media/base/media_tracks.h"
#include "media/base/test_data_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -83,14 +85,13 @@ void StreamParserTestBase::OnInitDone(
}
bool StreamParserTestBase::OnNewConfig(
- const AudioDecoderConfig& audio_config,
- const VideoDecoderConfig& video_config,
+ scoped_ptr<MediaTracks> tracks,
const StreamParser::TextTrackConfigMap& text_config) {
- DVLOG(1) << __FUNCTION__ << "(" << audio_config.IsValidConfig() << ", "
- << video_config.IsValidConfig() << ")";
- EXPECT_TRUE(audio_config.IsValidConfig());
- EXPECT_FALSE(video_config.IsValidConfig());
- last_audio_config_ = audio_config;
+ DVLOG(1) << __FUNCTION__ << " media tracks count=" << tracks->tracks().size();
+ EXPECT_EQ(tracks->tracks().size(), 1u);
+ EXPECT_TRUE(tracks->getFirstAudioConfig().IsValidConfig());
+ EXPECT_FALSE(tracks->getFirstVideoConfig().IsValidConfig());
+ last_audio_config_ = tracks->getFirstAudioConfig();
return true;
}
diff --git a/media/formats/common/stream_parser_test_base.h b/media/formats/common/stream_parser_test_base.h
index 42cb8d1..bdbfe7a 100644
--- a/media/formats/common/stream_parser_test_base.h
+++ b/media/formats/common/stream_parser_test_base.h
@@ -57,8 +57,7 @@ class StreamParserTestBase {
size_t length,
size_t piece_size);
void OnInitDone(const StreamParser::InitParameters& params);
- bool OnNewConfig(const AudioDecoderConfig& audio_config,
- const VideoDecoderConfig& video_config,
+ bool OnNewConfig(scoped_ptr<MediaTracks> tracks,
const StreamParser::TextTrackConfigMap& text_config);
bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers,
const StreamParser::BufferQueue& video_buffers,
diff --git a/media/formats/mp2t/mp2t_stream_parser.cc b/media/formats/mp2t/mp2t_stream_parser.cc
index 12c8a82..90a2b96 100644
--- a/media/formats/mp2t/mp2t_stream_parser.cc
+++ b/media/formats/mp2t/mp2t_stream_parser.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/stl_util.h"
+#include "media/base/media_tracks.h"
#include "media/base/stream_parser_buffer.h"
#include "media/base/text_track_config.h"
#include "media/base/timestamp_constants.h"
@@ -502,6 +503,21 @@ void Mp2tStreamParser::OnAudioConfigChanged(
}
}
+scoped_ptr<MediaTracks> GenerateMediaTrackInfo(
+ const AudioDecoderConfig& audio_config,
+ const VideoDecoderConfig& video_config) {
+ scoped_ptr<MediaTracks> media_tracks(new MediaTracks());
+ // TODO(servolk): Implement proper sourcing of media track info as described
+ // in crbug.com/590085
+ if (audio_config.IsValidConfig()) {
+ media_tracks->AddAudioTrack(audio_config, "audio", "main", "", "");
+ }
+ if (video_config.IsValidConfig()) {
+ media_tracks->AddVideoTrack(video_config, "video", "main", "", "");
+ }
+ return media_tracks;
+}
+
bool Mp2tStreamParser::FinishInitializationIfNeeded() {
// Nothing to be done if already initialized.
if (is_initialized_)
@@ -521,9 +537,9 @@ bool Mp2tStreamParser::FinishInitializationIfNeeded() {
return true;
// Pass the config before invoking the initialization callback.
- RCHECK(config_cb_.Run(queue_with_config.audio_config,
- queue_with_config.video_config,
- TextTrackConfigMap()));
+ scoped_ptr<MediaTracks> media_tracks = GenerateMediaTrackInfo(
+ queue_with_config.audio_config, queue_with_config.video_config);
+ RCHECK(config_cb_.Run(std::move(media_tracks), TextTrackConfigMap()));
queue_with_config.is_config_sent = true;
// For Mpeg2 TS, the duration is not known.
@@ -620,9 +636,9 @@ bool Mp2tStreamParser::EmitRemainingBuffers() {
// Update the audio and video config if needed.
BufferQueueWithConfig& queue_with_config = buffer_queue_chain_.front();
if (!queue_with_config.is_config_sent) {
- if (!config_cb_.Run(queue_with_config.audio_config,
- queue_with_config.video_config,
- TextTrackConfigMap()))
+ scoped_ptr<MediaTracks> media_tracks = GenerateMediaTrackInfo(
+ queue_with_config.audio_config, queue_with_config.video_config);
+ if (!config_cb_.Run(std::move(media_tracks), TextTrackConfigMap()))
return false;
queue_with_config.is_config_sent = true;
}
diff --git a/media/formats/mp2t/mp2t_stream_parser_unittest.cc b/media/formats/mp2t/mp2t_stream_parser_unittest.cc
index ab1d230..553f0c4 100644
--- a/media/formats/mp2t/mp2t_stream_parser_unittest.cc
+++ b/media/formats/mp2t/mp2t_stream_parser_unittest.cc
@@ -15,6 +15,8 @@
#include "base/time/time.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/decoder_buffer.h"
+#include "media/base/media_track.h"
+#include "media/base/media_tracks.h"
#include "media/base/stream_parser_buffer.h"
#include "media/base/test_data_util.h"
#include "media/base/text_track_config.h"
@@ -111,10 +113,12 @@ class Mp2tStreamParserTest : public testing::Test {
<< ", autoTimestampOffset=" << params.auto_update_timestamp_offset;
}
- bool OnNewConfig(const AudioDecoderConfig& ac,
- const VideoDecoderConfig& vc,
+ bool OnNewConfig(scoped_ptr<MediaTracks> tracks,
const StreamParser::TextTrackConfigMap& tc) {
- DVLOG(1) << "OnNewConfig: audio=" << ac.IsValidConfig()
+ const AudioDecoderConfig& ac = tracks->getFirstAudioConfig();
+ const VideoDecoderConfig& vc = tracks->getFirstVideoConfig();
+ DVLOG(1) << "OnNewConfig: media tracks count=" << tracks->tracks().size()
+ << ", audio=" << ac.IsValidConfig()
<< ", video=" << vc.IsValidConfig();
config_count_++;
EXPECT_TRUE(ac.IsValidConfig());
diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc
index 7becdf9..95abf83 100644
--- a/media/formats/mp4/mp4_stream_parser.cc
+++ b/media/formats/mp4/mp4_stream_parser.cc
@@ -14,6 +14,7 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "media/base/audio_decoder_config.h"
+#include "media/base/media_tracks.h"
#include "media/base/stream_parser_buffer.h"
#include "media/base/text_track_config.h"
#include "media/base/timestamp_constants.h"
@@ -353,7 +354,16 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
if (!moov_->pssh.empty())
OnEncryptedMediaInitData(moov_->pssh);
- RCHECK(config_cb_.Run(audio_config, video_config, TextTrackConfigMap()));
+ scoped_ptr<MediaTracks> media_tracks(new MediaTracks());
+ // TODO(servolk): Implement proper sourcing of media track info as described
+ // in crbug.com/590085
+ if (audio_config.IsValidConfig()) {
+ media_tracks->AddAudioTrack(audio_config, "audio", "", "", "");
+ }
+ if (video_config.IsValidConfig()) {
+ media_tracks->AddVideoTrack(video_config, "video", "", "", "");
+ }
+ RCHECK(config_cb_.Run(std::move(media_tracks), TextTrackConfigMap()));
StreamParser::InitParameters params(kInfiniteDuration());
if (moov_->extends.header.fragment_duration > 0) {
diff --git a/media/formats/mp4/mp4_stream_parser_unittest.cc b/media/formats/mp4/mp4_stream_parser_unittest.cc
index 635acd1..1fd2b75 100644
--- a/media/formats/mp4/mp4_stream_parser_unittest.cc
+++ b/media/formats/mp4/mp4_stream_parser_unittest.cc
@@ -15,6 +15,8 @@
#include "base/time/time.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/decoder_buffer.h"
+#include "media/base/media_track.h"
+#include "media/base/media_tracks.h"
#include "media/base/mock_media_log.h"
#include "media/base/stream_parser_buffer.h"
#include "media/base/test_data_util.h"
@@ -97,14 +99,14 @@ class MP4StreamParserTest : public testing::Test {
EXPECT_EQ(expected_liveness, params.liveness);
}
- bool NewConfigF(const AudioDecoderConfig& ac,
- const VideoDecoderConfig& vc,
+ bool NewConfigF(scoped_ptr<MediaTracks> tracks,
const StreamParser::TextTrackConfigMap& tc) {
- DVLOG(1) << "NewConfigF: audio=" << ac.IsValidConfig()
- << ", video=" << vc.IsValidConfig();
configs_received_ = true;
- audio_decoder_config_ = ac;
- video_decoder_config_ = vc;
+ audio_decoder_config_ = tracks->getFirstAudioConfig();
+ video_decoder_config_ = tracks->getFirstVideoConfig();
+ DVLOG(1) << "NewConfigF: track count=" << tracks->tracks().size()
+ << " audio=" << audio_decoder_config_.IsValidConfig()
+ << " video=" << video_decoder_config_.IsValidConfig();
return true;
}
diff --git a/media/formats/mpeg/mpeg_audio_stream_parser_base.cc b/media/formats/mpeg/mpeg_audio_stream_parser_base.cc
index ea2261f..2028495 100644
--- a/media/formats/mpeg/mpeg_audio_stream_parser_base.cc
+++ b/media/formats/mpeg/mpeg_audio_stream_parser_base.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/message_loop/message_loop.h"
+#include "media/base/media_tracks.h"
#include "media/base/stream_parser_buffer.h"
#include "media/base/text_track_config.h"
#include "media/base/timestamp_constants.h"
@@ -220,8 +221,11 @@ int MPEGAudioStreamParserBase::ParseFrame(const uint8_t* data,
timestamp_helper_.reset(new AudioTimestampHelper(sample_rate));
timestamp_helper_->SetBaseTimestamp(base_timestamp);
- VideoDecoderConfig video_config;
- if (!config_cb_.Run(config_, video_config, TextTrackConfigMap()))
+ scoped_ptr<MediaTracks> media_tracks(new MediaTracks());
+ if (config_.IsValidConfig()) {
+ media_tracks->AddAudioTrack(config_, "audio", "", "", "");
+ }
+ if (!config_cb_.Run(std::move(media_tracks), TextTrackConfigMap()))
return -1;
if (!init_cb_.is_null()) {
diff --git a/media/formats/webm/webm_stream_parser.cc b/media/formats/webm/webm_stream_parser.cc
index e36a972..3090768 100644
--- a/media/formats/webm/webm_stream_parser.cc
+++ b/media/formats/webm/webm_stream_parser.cc
@@ -9,6 +9,8 @@
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
+#include "media/base/media_track.h"
+#include "media/base/media_tracks.h"
#include "media/base/timestamp_constants.h"
#include "media/formats/webm/webm_cluster_parser.h"
#include "media/formats/webm/webm_constants.h"
@@ -222,9 +224,16 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8_t* data, int size) {
if (video_config.is_encrypted())
OnEncryptedMediaInitData(tracks_parser.video_encryption_key_id());
- if (!config_cb_.Run(audio_config,
- video_config,
- tracks_parser.text_tracks())) {
+ scoped_ptr<MediaTracks> media_tracks(new MediaTracks());
+ // TODO(servolk): Implement proper sourcing of media track info as described
+ // in crbug.com/590085
+ if (audio_config.IsValidConfig()) {
+ media_tracks->AddAudioTrack(audio_config, "audio", "", "", "");
+ }
+ if (video_config.IsValidConfig()) {
+ media_tracks->AddVideoTrack(video_config, "video", "", "", "");
+ }
+ if (!config_cb_.Run(std::move(media_tracks), tracks_parser.text_tracks())) {
DVLOG(1) << "New config data isn't allowed.";
return -1;
}
diff --git a/media/media.gyp b/media/media.gyp
index 825dc85..5fe1f159 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -363,6 +363,10 @@
'base/media_resources.h',
'base/media_switches.cc',
'base/media_switches.h',
+ 'base/media_track.cc',
+ 'base/media_track.h',
+ 'base/media_tracks.cc',
+ 'base/media_tracks.h',
'base/media_util.cc',
'base/media_util.h',
'base/mime_util.cc',
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc
index 80871f9..51a845b 100644
--- a/media/test/pipeline_integration_test.cc
+++ b/media/test/pipeline_integration_test.cc
@@ -21,6 +21,7 @@
#include "media/base/media.h"
#include "media/base/media_keys.h"
#include "media/base/media_switches.h"
+#include "media/base/media_tracks.h"
#include "media/base/test_data_util.h"
#include "media/base/timestamp_constants.h"
#include "media/cdm/aes_decryptor.h"
@@ -636,7 +637,7 @@ class MockMediaSource {
return last_timestamp_offset_;
}
- MOCK_METHOD0(InitSegmentReceived, void(void));
+ MOCK_METHOD1(InitSegmentReceived, void(const MediaTracks&));
private:
scoped_refptr<DecoderBuffer> file_data_;
@@ -682,7 +683,7 @@ class PipelineIntegrationTestHost : public testing::Test,
class PipelineIntegrationTest : public PipelineIntegrationTestHost {
public:
void StartPipelineWithMediaSource(MockMediaSource* source) {
- EXPECT_CALL(*source, InitSegmentReceived()).Times(AtLeast(1));
+ EXPECT_CALL(*source, InitSegmentReceived(_)).Times(AtLeast(1));
EXPECT_CALL(*this, OnMetadata(_))
.Times(AtMost(1))
.WillRepeatedly(SaveArg<0>(&metadata_));
@@ -726,7 +727,7 @@ class PipelineIntegrationTest : public PipelineIntegrationTestHost {
void StartPipelineWithEncryptedMedia(MockMediaSource* source,
FakeEncryptedMedia* encrypted_media) {
- EXPECT_CALL(*source, InitSegmentReceived()).Times(AtLeast(1));
+ EXPECT_CALL(*source, InitSegmentReceived(_)).Times(AtLeast(1));
EXPECT_CALL(*this, OnMetadata(_))
.Times(AtMost(1))
.WillRepeatedly(SaveArg<0>(&metadata_));