Commit 37e3ddb2 authored by wolenetz's avatar wolenetz Committed by Commit bot

MSE: Notify Blink SourceBuffer on init segment received

As the second of a three-sided set of change:
This change lays the groundwork for Blink to own the app-visible pieces
of the MSE initialization segment received algorithm. It lets
SourceState notify WebSourceBufferImpl upon parsing an initialization
segment. WSBI then notifies its WebSourceBufferClient.
Updated unit tests are included.

R=acolwell@chromium.org
TEST=No media_unittest regression
BUG=249428,397243

Review URL: https://codereview.chromium.org/547223003

Cr-Commit-Position: refs/heads/master@{#294722}
parent 069fc881
......@@ -6,8 +6,12 @@
#include <limits>
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/float_util.h"
#include "media/filters/chunk_demuxer.h"
#include "third_party/WebKit/public/platform/WebSourceBufferClient.h"
namespace media {
......@@ -34,12 +38,20 @@ WebSourceBufferImpl::WebSourceBufferImpl(
const std::string& id, ChunkDemuxer* demuxer)
: id_(id),
demuxer_(demuxer),
client_(NULL),
append_window_end_(kInfiniteDuration()) {
DCHECK(demuxer_);
}
WebSourceBufferImpl::~WebSourceBufferImpl() {
DCHECK(!demuxer_) << "Object destroyed w/o removedFromMediaSource() call";
DCHECK(!client_);
}
void WebSourceBufferImpl::setClient(blink::WebSourceBufferClient* client) {
DCHECK(client);
DCHECK(!client_);
client_ = client;
}
bool WebSourceBufferImpl::setMode(WebSourceBuffer::AppendMode mode) {
......@@ -76,7 +88,9 @@ void WebSourceBufferImpl::append(
base::TimeDelta old_offset = timestamp_offset_;
demuxer_->AppendData(id_, data, length,
append_window_start_, append_window_end_,
&timestamp_offset_);
&timestamp_offset_,
base::Bind(&WebSourceBufferImpl::InitSegmentReceived,
base::Unretained(this)));
// Coded frame processing may update the timestamp offset. If the caller
// provides a non-NULL |timestamp_offset| and frame processing changes the
......@@ -129,6 +143,12 @@ void WebSourceBufferImpl::setAppendWindowEnd(double end) {
void WebSourceBufferImpl::removedFromMediaSource() {
demuxer_->RemoveId(id_);
demuxer_ = NULL;
client_ = NULL;
}
void WebSourceBufferImpl::InitSegmentReceived() {
DVLOG(1) << __FUNCTION__;
client_->initializationSegmentReceived();
}
} // namespace media
......@@ -21,6 +21,7 @@ class WebSourceBufferImpl : public blink::WebSourceBuffer {
virtual ~WebSourceBufferImpl();
// blink::WebSourceBuffer implementation.
virtual void setClient(blink::WebSourceBufferClient* client);
virtual bool setMode(AppendMode mode);
virtual blink::WebTimeRanges buffered();
virtual void append(
......@@ -35,9 +36,15 @@ class WebSourceBufferImpl : public blink::WebSourceBuffer {
virtual void removedFromMediaSource();
private:
// Demuxer callback handler to process an initialization segment received
// during an append() call.
void InitSegmentReceived();
std::string id_;
ChunkDemuxer* demuxer_; // Owned by WebMediaPlayerImpl.
blink::WebSourceBufferClient* client_;
// Controls the offset applied to timestamps when processing appended media
// segments. It is initially 0, which indicates that no offset is being
// applied. Both setTimestampOffset() and append() may update this value.
......
......@@ -90,6 +90,8 @@ class SourceState {
typedef base::Callback<ChunkDemuxerStream*(
DemuxerStream::Type)> CreateDemuxerStreamCB;
typedef ChunkDemuxer::InitSegmentReceivedCB InitSegmentReceivedCB;
typedef base::Callback<void(
ChunkDemuxerStream*, const TextTrackConfig&)> NewTextTrackCB;
......@@ -111,11 +113,14 @@ class SourceState {
// error occurred. |*timestamp_offset| is used and possibly updated by the
// append. |append_window_start| and |append_window_end| correspond to the MSE
// spec's similarly named source buffer attributes that are used in coded
// frame processing.
bool Append(const uint8* data, size_t length,
// frame processing. |init_segment_received_cb| is run for each new fully
// parsed initialization segment.
bool Append(const uint8* data,
size_t length,
TimeDelta append_window_start,
TimeDelta append_window_end,
TimeDelta* timestamp_offset);
TimeDelta* timestamp_offset,
const InitSegmentReceivedCB& init_segment_received_cb);
// Aborts the current append sequence and resets the parser.
void Abort(TimeDelta append_window_start,
......@@ -232,6 +237,13 @@ class SourceState {
LogCB log_cb_;
StreamParser::InitCB init_cb_;
// During Append(), OnNewConfigs() will trigger the initialization segment
// received algorithm. This callback is only non-NULL during the lifetime of
// an Append() call. Note, the MSE spec explicitly disallows this algorithm
// during an Abort(), since Abort() is allowed only to emit coded frames, and
// only if the parser is PARSING_MEDIA_SEGMENT (not an INIT segment).
InitSegmentReceivedCB init_segment_received_cb_;
// 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
......@@ -300,20 +312,27 @@ void SourceState::SetGroupStartTimestampIfInSequenceMode(
frame_processor_->SetGroupStartTimestampIfInSequenceMode(timestamp_offset);
}
bool SourceState::Append(const uint8* data, size_t length,
TimeDelta append_window_start,
TimeDelta append_window_end,
TimeDelta* timestamp_offset) {
bool SourceState::Append(
const uint8* data,
size_t length,
TimeDelta append_window_start,
TimeDelta append_window_end,
TimeDelta* timestamp_offset,
const InitSegmentReceivedCB& init_segment_received_cb) {
DCHECK(timestamp_offset);
DCHECK(!timestamp_offset_during_append_);
DCHECK(!init_segment_received_cb.is_null());
DCHECK(init_segment_received_cb_.is_null());
append_window_start_during_append_ = append_window_start;
append_window_end_during_append_ = append_window_end;
timestamp_offset_during_append_ = timestamp_offset;
init_segment_received_cb_= init_segment_received_cb;
// TODO(wolenetz/acolwell): Curry and pass a NewBuffersCB here bound with
// append window and timestamp offset pointer. See http://crbug.com/351454.
bool err = stream_parser_->Parse(data, length);
timestamp_offset_during_append_ = NULL;
init_segment_received_cb_.Reset();
return err;
}
......@@ -534,6 +553,7 @@ bool SourceState::OnNewConfigs(
DVLOG(1) << "OnNewConfigs(" << allow_audio << ", " << allow_video
<< ", " << audio_config.IsValidConfig()
<< ", " << video_config.IsValidConfig() << ")";
DCHECK(!init_segment_received_cb_.is_null());
if (!audio_config.IsValidConfig() && !video_config.IsValidConfig()) {
DVLOG(1) << "OnNewConfigs() : Audio & video config are not valid!";
......@@ -676,6 +696,9 @@ bool SourceState::OnNewConfigs(
frame_processor_->SetAllTrackBuffersNeedRandomAccessPoint();
DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed");
if (success)
init_segment_received_cb_.Run();
return success;
}
......@@ -1238,15 +1261,19 @@ Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const {
return itr->second->GetBufferedRanges(duration_, state_ == ENDED);
}
void ChunkDemuxer::AppendData(const std::string& id,
const uint8* data, size_t length,
TimeDelta append_window_start,
TimeDelta append_window_end,
TimeDelta* timestamp_offset) {
void ChunkDemuxer::AppendData(
const std::string& id,
const uint8* data,
size_t length,
TimeDelta append_window_start,
TimeDelta append_window_end,
TimeDelta* timestamp_offset,
const InitSegmentReceivedCB& init_segment_received_cb) {
DVLOG(1) << "AppendData(" << id << ", " << length << ")";
DCHECK(!id.empty());
DCHECK(timestamp_offset);
DCHECK(!init_segment_received_cb.is_null());
Ranges<TimeDelta> ranges;
......@@ -1269,7 +1296,8 @@ void ChunkDemuxer::AppendData(const std::string& id,
if (!source_state_map_[id]->Append(data, length,
append_window_start,
append_window_end,
timestamp_offset)) {
timestamp_offset,
init_segment_received_cb)) {
ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
return;
}
......@@ -1280,7 +1308,8 @@ void ChunkDemuxer::AppendData(const std::string& id,
if (!source_state_map_[id]->Append(data, length,
append_window_start,
append_window_end,
timestamp_offset)) {
timestamp_offset,
init_segment_received_cb)) {
ReportError_Locked(PIPELINE_ERROR_DECODE);
return;
}
......
......@@ -137,6 +137,8 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
kReachedIdLimit, // Reached ID limit. We can't handle any more IDs.
};
typedef base::Closure InitSegmentReceivedCB;
// |open_cb| Run when Initialize() is called to signal that the demuxer
// is ready to receive media data via AppenData().
// |need_key_cb| Run when the demuxer determines that an encryption key is
......@@ -211,10 +213,13 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
// |append_window_start| and |append_window_end| correspond to the MSE spec's
// similarly named source buffer attributes that are used in coded frame
// processing.
// |init_segment_received_cb| is run for each newly successfully parsed
// initialization segment.
void AppendData(const std::string& id, const uint8* data, size_t length,
base::TimeDelta append_window_start,
base::TimeDelta append_window_end,
base::TimeDelta* timestamp_offset);
base::TimeDelta* timestamp_offset,
const InitSegmentReceivedCB& init_segment_received_cb);
// Aborts parsing the current segment and reset the parser to a state where
// it can accept a new segment.
......
......@@ -162,6 +162,9 @@ class ChunkDemuxerTest : public ::testing::Test {
ChunkDemuxerTest()
: append_window_end_for_next_append_(kInfiniteDuration()) {
init_segment_received_cb_ =
base::Bind(&ChunkDemuxerTest::InitSegmentReceived,
base::Unretained(this));
CreateNewDemuxer();
}
......@@ -573,7 +576,8 @@ class ChunkDemuxerTest : public ::testing::Test {
demuxer_->AppendData(source_id, data, length,
append_window_start_for_next_append_,
append_window_end_for_next_append_,
&timestamp_offset_map_[source_id]);
&timestamp_offset_map_[source_id],
init_segment_received_cb_);
}
void AppendDataInPieces(const uint8* data, size_t length) {
......@@ -664,6 +668,14 @@ class ChunkDemuxerTest : public ::testing::Test {
expected_duration = kDefaultDuration();
EXPECT_CALL(*this, DemuxerOpened());
// Adding expectation prior to CreateInitDoneCB() here because InSequence
// tests require init segment received before duration set. Also, only
// expect an init segment received callback if there is actually a track in
// it.
if (stream_flags != 0)
EXPECT_CALL(*this, InitSegmentReceived());
demuxer_->Initialize(
&host_, CreateInitDoneCB(expected_duration, expected_status), true);
......@@ -696,7 +708,9 @@ class ChunkDemuxerTest : public ::testing::Test {
video_flags |= HAS_TEXT;
}
EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegmentWithSourceId(audio_id, audio_flags);
EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegmentWithSourceId(video_id, video_flags);
return true;
}
......@@ -729,6 +743,9 @@ class ChunkDemuxerTest : public ::testing::Test {
EXPECT_CALL(*this, DemuxerOpened());
// Adding expectation prior to CreateInitDoneCB() here because InSequence
// tests require init segment received before duration set.
EXPECT_CALL(*this, InitSegmentReceived());
demuxer_->Initialize(
&host_, CreateInitDoneCB(base::TimeDelta::FromMilliseconds(2744),
PIPELINE_OK), true);
......@@ -755,6 +772,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());
AppendData(bear2->data(), 4340);
// Append a media segment that goes from [0.527000, 1.014000).
......@@ -763,6 +781,7 @@ class ChunkDemuxerTest : public ::testing::Test {
// Append initialization segment for bear1 & fill gap with [779-1197)
// segment.
EXPECT_CALL(*this, InitSegmentReceived());
AppendData(bear1->data(), 4370);
AppendData(bear1->data() + 72737, 28183);
CheckExpectedRanges(kSourceId, "{ [0,2736) }");
......@@ -1098,6 +1117,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());
AppendDataInPieces(buffer->data(), buffer->data_size(), 512);
// Verify that the timestamps on the first few packets match what we
......@@ -1142,6 +1162,8 @@ class ChunkDemuxerTest : public ::testing::Test {
NeedKeyMock(type, init_data_ptr, init_data.size());
}
MOCK_METHOD0(InitSegmentReceived, void(void));
void Seek(base::TimeDelta seek_time) {
demuxer_->StartWaitingForSeek(seek_time);
demuxer_->Seek(seek_time, NewExpectedStatusCB(PIPELINE_OK));
......@@ -1166,6 +1188,7 @@ class ChunkDemuxerTest : public ::testing::Test {
MockDemuxerHost host_;
scoped_ptr<ChunkDemuxer> demuxer_;
ChunkDemuxer::InitSegmentReceivedCB init_segment_received_cb_;
base::TimeDelta append_window_start_for_next_append_;
base::TimeDelta append_window_end_for_next_append_;
......@@ -1348,10 +1371,12 @@ TEST_F(ChunkDemuxerTest, SingleTextTrackIdChange) {
CreateInitSegmentWithAlternateTextTrackNum(HAS_TEXT | HAS_AUDIO | HAS_VIDEO,
false, false,
&info_tracks, &info_tracks_size);
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_,
&timestamp_offset_map_[kSourceId]);
&timestamp_offset_map_[kSourceId],
init_segment_received_cb_);
AppendMuxedCluster(
MuxedStreamInfo(kAudioTrackNum, "46K 69K"),
......@@ -1389,6 +1414,7 @@ TEST_F(ChunkDemuxerTest, InitSegmentSetsNeedRandomAccessPointFlag) {
MuxedStreamInfo(kTextTrackNum, "25K 40K"));
CheckExpectedRanges(kSourceId, "{ [23,46) }");
EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegment(HAS_TEXT | HAS_AUDIO | HAS_VIDEO);
AppendMuxedCluster(
MuxedStreamInfo(kAudioTrackNum, "46K 69K"),
......@@ -1412,6 +1438,7 @@ TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppended) {
EXPECT_EQ(AddId("audio", HAS_AUDIO), ChunkDemuxer::kOk);
EXPECT_EQ(AddId("video", HAS_VIDEO), ChunkDemuxer::kOk);
EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegmentWithSourceId("audio", HAS_AUDIO);
ShutdownDemuxer();
......@@ -1429,6 +1456,7 @@ TEST_F(ChunkDemuxerTest, Shutdown_BeforeAllInitSegmentsAppendedText) {
EXPECT_CALL(host_, AddTextStream(_, _))
.Times(Exactly(1));
EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegmentWithSourceId("video_and_text", HAS_VIDEO | HAS_TEXT);
ShutdownDemuxer();
......@@ -1537,7 +1565,8 @@ TEST_F(ChunkDemuxerTest, AppendDataBeforeInit) {
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]);
&timestamp_offset_map_[kSourceId],
init_segment_received_cb_);
}
// Make sure Read() callbacks are dispatched with the proper data.
......@@ -1573,7 +1602,8 @@ TEST_F(ChunkDemuxerTest, OutOfOrderClusters) {
demuxer_->AppendData(kSourceId, cluster_c->data(), cluster_c->size(),
append_window_start_for_next_append_,
append_window_end_for_next_append_,
&timestamp_offset_map_[kSourceId]);
&timestamp_offset_map_[kSourceId],
init_segment_received_cb_);
}
TEST_F(ChunkDemuxerTest, NonMonotonicButAboveClusterTimecode) {
......@@ -1598,7 +1628,8 @@ TEST_F(ChunkDemuxerTest, NonMonotonicButAboveClusterTimecode) {
demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size(),
append_window_start_for_next_append_,
append_window_end_for_next_append_,
&timestamp_offset_map_[kSourceId]);
&timestamp_offset_map_[kSourceId],
init_segment_received_cb_);
}
TEST_F(ChunkDemuxerTest, BackwardsAndBeforeClusterTimecode) {
......@@ -1623,7 +1654,8 @@ TEST_F(ChunkDemuxerTest, BackwardsAndBeforeClusterTimecode) {
demuxer_->AppendData(kSourceId, cluster_b->data(), cluster_b->size(),
append_window_start_for_next_append_,
append_window_end_for_next_append_,
&timestamp_offset_map_[kSourceId]);
&timestamp_offset_map_[kSourceId],
init_segment_received_cb_);
}
......@@ -1934,6 +1966,7 @@ TEST_F(ChunkDemuxerTest, AppendingInPieces) {
memcpy(dst, cluster_b->data(), cluster_b->size());
dst += cluster_b->size();
EXPECT_CALL(*this, InitSegmentReceived());
AppendDataInPieces(buffer.get(), buffer_size);
GenerateExpectedReads(0, 9);
......@@ -2092,7 +2125,8 @@ TEST_F(ChunkDemuxerTest, ParseErrorDuringInit) {
demuxer_->AppendData(kSourceId, &tmp, 1,
append_window_start_for_next_append_,
append_window_end_for_next_append_,
&timestamp_offset_map_[kSourceId]);
&timestamp_offset_map_[kSourceId],
init_segment_received_cb_);
}
TEST_F(ChunkDemuxerTest, AVHeadersWithAudioOnlyType) {
......@@ -2129,6 +2163,7 @@ TEST_F(ChunkDemuxerTest, MultipleHeaders) {
AppendCluster(kDefaultFirstCluster());
// Append another identical initialization segment.
EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegment(HAS_AUDIO | HAS_VIDEO);
AppendCluster(kDefaultSecondCluster());
......@@ -2183,6 +2218,7 @@ TEST_F(ChunkDemuxerTest, AddIdFailures) {
// Adding an id with audio/video should fail because we already added audio.
ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit);
EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegmentWithSourceId(audio_id, HAS_AUDIO);
// Adding an id after append should fail.
......@@ -2415,6 +2451,7 @@ TEST_F(ChunkDemuxerTest, GetBufferedRanges_AudioIdOnly) {
&host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
ASSERT_EQ(AddId(kSourceId, HAS_AUDIO), ChunkDemuxer::kOk);
EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegment(HAS_AUDIO);
// Test a simple cluster.
......@@ -2437,6 +2474,7 @@ TEST_F(ChunkDemuxerTest, GetBufferedRanges_VideoIdOnly) {
&host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true);
ASSERT_EQ(AddId(kSourceId, HAS_VIDEO), ChunkDemuxer::kOk);
EXPECT_CALL(*this, InitSegmentReceived());
AppendInitSegment(HAS_VIDEO);
// Test a simple cluster.
......@@ -3015,6 +3053,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());
AppendData(kSourceId, buffer->data(), buffer->data_size());
// Confirm we're in the middle of parsing a media segment.
......@@ -3058,6 +3097,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());
AppendData(kSourceId, buffer->data(), buffer->data_size());
// Confirm we're in the middle of parsing a media segment.
......@@ -3447,6 +3487,7 @@ TEST_F(ChunkDemuxerTest, AppendWindow_WebMFile_AudioOnly) {
// partial append window trim must come from a previous Append() call.
scoped_refptr<DecoderBuffer> buffer =
ReadTestDataFile("bear-320x240-audio-only.webm");
EXPECT_CALL(*this, InitSegmentReceived());
AppendDataInPieces(buffer->data(), buffer->data_size(), 128);
DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::AUDIO);
......@@ -3473,6 +3514,7 @@ TEST_F(ChunkDemuxerTest, AppendWindow_AudioConfigUpdateRemovesPreroll) {
// Read a WebM file into memory and append the data.
scoped_refptr<DecoderBuffer> buffer =
ReadTestDataFile("bear-320x240-audio-only.webm");
EXPECT_CALL(*this, InitSegmentReceived());
AppendDataInPieces(buffer->data(), buffer->data_size(), 512);
CheckExpectedRanges(kSourceId, "{ }");
......@@ -3482,6 +3524,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(host_, SetDuration(_)).Times(AnyNumber());
ASSERT_TRUE(SetTimestampOffset(kSourceId, duration_1));
AppendDataInPieces(buffer2->data(), buffer2->data_size(), 512);
......
......@@ -18,9 +18,11 @@
#include "media/cdm/json_web_key.h"
#include "media/filters/chunk_demuxer.h"
#include "media/filters/renderer_impl.h"
#include "testing/gmock/include/gmock/gmock.h"
using testing::_;
using testing::AnyNumber;
using testing::AtLeast;
using testing::AtMost;
using testing::SaveArg;
......@@ -432,7 +434,9 @@ class MockMediaSource {
chunk_demuxer_->AppendData(
kSourceId, file_data_->data() + current_position_, size,
base::TimeDelta(), kInfiniteDuration(), &last_timestamp_offset_);
base::TimeDelta(), kInfiniteDuration(), &last_timestamp_offset_,
base::Bind(&MockMediaSource::InitSegmentReceived,
base::Unretained(this)));
current_position_ += size;
}
......@@ -442,7 +446,9 @@ class MockMediaSource {
CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId));
chunk_demuxer_->AppendData(kSourceId, pData, size,
base::TimeDelta(), kInfiniteDuration(),
&timestamp_offset);
&timestamp_offset,
base::Bind(&MockMediaSource::InitSegmentReceived,
base::Unretained(this)));
last_timestamp_offset_ = timestamp_offset;
}
......@@ -457,7 +463,9 @@ class MockMediaSource {
size,
append_window_start,
append_window_end,
&timestamp_offset);
&timestamp_offset,
base::Bind(&MockMediaSource::InitSegmentReceived,
base::Unretained(this)));
last_timestamp_offset_ = timestamp_offset;
}
......@@ -519,6 +527,8 @@ class MockMediaSource {
return last_timestamp_offset_;
}
MOCK_METHOD0(InitSegmentReceived, void(void));
private:
base::FilePath file_path_;
scoped_refptr<DecoderBuffer> file_data_;
......@@ -536,6 +546,7 @@ class PipelineIntegrationTest
public PipelineIntegrationTestBase {
public:
void StartPipelineWithMediaSource(MockMediaSource* source) {
EXPECT_CALL(*source, InitSegmentReceived()).Times(AtLeast(1));
EXPECT_CALL(*this, OnMetadata(_))
.Times(AtMost(1))
.WillRepeatedly(SaveArg<0>(&metadata_));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment