Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1102)

Unified Diff: media/filters/ffmpeg_demuxer.cc

Issue 11420070: Remove locking from FFmpegDemuxerStream and associated TODOs from media code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | media/filters/ffmpeg_video_decoder.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/ffmpeg_demuxer.cc
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index 404a52a852d1e9a94a91f9c8a3f193c83aa31bf7..64f84011f6918936aaa0e1a7ff3132f26c177077 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -35,6 +35,7 @@ FFmpegDemuxerStream::FFmpegDemuxerStream(
FFmpegDemuxer* demuxer,
AVStream* stream)
: demuxer_(demuxer),
+ message_loop_(base::MessageLoopProxy::current()),
stream_(stream),
type_(UNKNOWN),
stopped_(false),
@@ -67,17 +68,15 @@ FFmpegDemuxerStream::FFmpegDemuxerStream(
}
bool FFmpegDemuxerStream::HasPendingReads() {
- DCHECK(demuxer_->message_loop()->BelongsToCurrentThread());
- base::AutoLock auto_lock(lock_);
+ DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK(!stopped_ || read_queue_.empty())
<< "Read queue should have been emptied if demuxing stream is stopped";
return !read_queue_.empty();
}
void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) {
- DCHECK(demuxer_->message_loop()->BelongsToCurrentThread());
+ DCHECK(message_loop_->BelongsToCurrentThread());
- base::AutoLock auto_lock(lock_);
if (stopped_) {
NOTREACHED() << "Attempted to enqueue packet on a stopped stream";
return;
@@ -105,33 +104,28 @@ void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) {
last_packet_timestamp_ != kNoTimestamp() &&
last_packet_timestamp_ < buffer->GetTimestamp()) {
buffered_ranges_.Add(last_packet_timestamp_, buffer->GetTimestamp());
- demuxer_->message_loop()->PostTask(FROM_HERE, base::Bind(
- &FFmpegDemuxer::NotifyBufferingChanged, demuxer_));
+ demuxer_->NotifyBufferingChanged();
}
last_packet_timestamp_ = buffer->GetTimestamp();
}
buffer_queue_.push_back(buffer);
- FulfillPendingRead();
- return;
+ SatisfyPendingReads();
}
void FFmpegDemuxerStream::FlushBuffers() {
- DCHECK(demuxer_->message_loop()->BelongsToCurrentThread());
- base::AutoLock auto_lock(lock_);
+ DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK(read_queue_.empty()) << "Read requests should be empty";
buffer_queue_.clear();
last_packet_timestamp_ = kNoTimestamp();
}
void FFmpegDemuxerStream::Stop() {
- DCHECK(demuxer_->message_loop()->BelongsToCurrentThread());
- base::AutoLock auto_lock(lock_);
+ DCHECK(message_loop_->BelongsToCurrentThread());
buffer_queue_.clear();
for (ReadQueue::iterator it = read_queue_.begin();
it != read_queue_.end(); ++it) {
- it->Run(DemuxerStream::kOk,
- scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer()));
+ it->Run(DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer());
}
read_queue_.clear();
stopped_ = true;
@@ -146,76 +140,31 @@ DemuxerStream::Type FFmpegDemuxerStream::type() {
}
void FFmpegDemuxerStream::Read(const ReadCB& read_cb) {
- DCHECK(!read_cb.is_null());
-
- base::AutoLock auto_lock(lock_);
- // Don't accept any additional reads if we've been told to stop.
- // The demuxer_ may have been destroyed in the pipleine thread.
- //
- // TODO(scherkus): it would be cleaner if we replied with an error message.
- if (stopped_) {
- read_cb.Run(DemuxerStream::kOk,
- scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer()));
+ if (!message_loop_->BelongsToCurrentThread()) {
+ message_loop_->PostTask(FROM_HERE, base::Bind(
+ &FFmpegDemuxerStream::Read, this, read_cb));
return;
}
- // Buffers are only queued when there are no pending reads.
- DCHECK(buffer_queue_.empty() || read_queue_.empty());
-
- if (buffer_queue_.empty()) {
- demuxer_->message_loop()->PostTask(FROM_HERE, base::Bind(
- &FFmpegDemuxerStream::ReadTask, this, read_cb));
- return;
- }
-
- // Send the oldest buffer back.
- scoped_refptr<DecoderBuffer> buffer = buffer_queue_.front();
- buffer_queue_.pop_front();
- read_cb.Run(DemuxerStream::kOk, buffer);
-}
-
-void FFmpegDemuxerStream::ReadTask(const ReadCB& read_cb) {
- DCHECK(demuxer_->message_loop()->BelongsToCurrentThread());
-
- base::AutoLock auto_lock(lock_);
// Don't accept any additional reads if we've been told to stop.
+ // The |demuxer_| may have been destroyed in the pipeline thread.
//
- // TODO(scherkus): it would be cleaner if we replied with an error message.
+ // TODO(scherkus): it would be cleaner to reply with an error message.
if (stopped_) {
- read_cb.Run(DemuxerStream::kOk,
- scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer()));
+ read_cb.Run(DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer());
return;
}
- // Enqueue the callback and attempt to satisfy it immediately.
read_queue_.push_back(read_cb);
- FulfillPendingRead();
-
- // Check if there are still pending reads, demux some more.
- if (!read_queue_.empty()) {
- demuxer_->PostDemuxTask();
- }
+ SatisfyPendingReads();
}
-void FFmpegDemuxerStream::FulfillPendingRead() {
- DCHECK(demuxer_->message_loop()->BelongsToCurrentThread());
- lock_.AssertAcquired();
- if (buffer_queue_.empty() || read_queue_.empty()) {
+void FFmpegDemuxerStream::EnableBitstreamConverter() {
+ if (!message_loop_->BelongsToCurrentThread()) {
+ message_loop_->PostTask(FROM_HERE, base::Bind(
+ &FFmpegDemuxerStream::EnableBitstreamConverter, this));
return;
}
-
- // Dequeue a buffer and pending read pair.
- scoped_refptr<DecoderBuffer> buffer = buffer_queue_.front();
- ReadCB read_cb(read_queue_.front());
- buffer_queue_.pop_front();
- read_queue_.pop_front();
-
- // Execute the callback.
- read_cb.Run(DemuxerStream::kOk, buffer);
-}
-
-void FFmpegDemuxerStream::EnableBitstreamConverter() {
- base::AutoLock auto_lock(lock_);
CHECK(bitstream_converter_.get());
bitstream_converter_enabled_ = true;
}
@@ -231,7 +180,6 @@ const VideoDecoderConfig& FFmpegDemuxerStream::video_decoder_config() {
}
FFmpegDemuxerStream::~FFmpegDemuxerStream() {
- base::AutoLock auto_lock(lock_);
DCHECK(stopped_);
DCHECK(read_queue_.empty());
DCHECK(buffer_queue_.empty());
@@ -242,10 +190,28 @@ base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const {
}
Ranges<base::TimeDelta> FFmpegDemuxerStream::GetBufferedRanges() const {
- base::AutoLock auto_lock(lock_);
return buffered_ranges_;
}
+void FFmpegDemuxerStream::SatisfyPendingReads() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ while (!read_queue_.empty() && !buffer_queue_.empty()) {
+ ReadCB read_cb = read_queue_.front();
+ read_queue_.pop_front();
+
+ // Send earliest buffer back on a new execution stack to avoid recursing.
+ scoped_refptr<DecoderBuffer> buffer = buffer_queue_.front();
+ buffer_queue_.pop_front();
+ message_loop_->PostTask(FROM_HERE, base::Bind(
+ read_cb, DemuxerStream::kOk, buffer));
+ }
+
+ // No buffers but pending reads? Ask for more!
+ if (!read_queue_.empty() && buffer_queue_.empty()) {
+ demuxer_->NotifyHasPendingRead();
+ }
+}
+
// static
base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp(
const AVRational& time_base, int64 timestamp) {
@@ -277,11 +243,6 @@ FFmpegDemuxer::FFmpegDemuxer(
FFmpegDemuxer::~FFmpegDemuxer() {}
-void FFmpegDemuxer::PostDemuxTask() {
- message_loop_->PostTask(FROM_HERE,
- base::Bind(&FFmpegDemuxer::DemuxTask, this));
-}
-
void FFmpegDemuxer::Stop(const base::Closure& callback) {
// Post a task to notify the streams to stop as well.
message_loop_->PostTask(FROM_HERE,
@@ -329,10 +290,6 @@ base::TimeDelta FFmpegDemuxer::GetStartTime() const {
return start_time_;
}
-scoped_refptr<base::MessageLoopProxy> FFmpegDemuxer::message_loop() {
- return message_loop_;
-}
-
// Helper for calculating the bitrate of the media based on information stored
// in |format_context| or failing that the size and duration of the media.
//
@@ -600,9 +557,6 @@ void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) {
}
// Queue the packet with the appropriate stream.
- // TODO(scherkus): should we post this back to the pipeline thread? I'm
- // worried about downstream filters (i.e., decoders) executing on this
- // thread.
DCHECK_GE(packet->stream_index, 0);
DCHECK_LT(packet->stream_index, static_cast<int>(streams_.size()));
@@ -619,7 +573,8 @@ void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) {
// Create a loop by posting another task. This allows seek and message loop
// quit tasks to get processed.
if (StreamsHavePendingReads()) {
- PostDemuxTask();
+ message_loop_->PostTask(FROM_HERE, base::Bind(
+ &FFmpegDemuxer::DemuxTask, this));
}
}
@@ -681,6 +636,11 @@ void FFmpegDemuxer::StreamHasEnded() {
}
}
+void FFmpegDemuxer::NotifyHasPendingRead() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DemuxTask();
+}
+
void FFmpegDemuxer::NotifyBufferingChanged() {
DCHECK(message_loop_->BelongsToCurrentThread());
Ranges<base::TimeDelta> buffered;
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | media/filters/ffmpeg_video_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698