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

Side by Side Diff: media/filters/ffmpeg_demuxer.cc

Issue 6171009: Remove MessageLoop methods from Filter interface (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Applied more CR suggestions & removed message_loop() methods where possible. Created 9 years, 11 months 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | media/filters/ffmpeg_demuxer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/callback.h" 5 #include "base/callback.h"
6 #include "base/command_line.h" 6 #include "base/command_line.h"
7 #include "base/message_loop.h" 7 #include "base/message_loop.h"
8 #include "base/scoped_ptr.h" 8 #include "base/scoped_ptr.h"
9 #include "base/stl_util-inl.h" 9 #include "base/stl_util-inl.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 const AVRational& time_base, int64 timestamp) { 232 const AVRational& time_base, int64 timestamp) {
233 if (timestamp == static_cast<int64>(AV_NOPTS_VALUE)) 233 if (timestamp == static_cast<int64>(AV_NOPTS_VALUE))
234 return kNoTimestamp; 234 return kNoTimestamp;
235 235
236 return ConvertTimestamp(time_base, timestamp); 236 return ConvertTimestamp(time_base, timestamp);
237 } 237 }
238 238
239 // 239 //
240 // FFmpegDemuxer 240 // FFmpegDemuxer
241 // 241 //
242 FFmpegDemuxer::FFmpegDemuxer() 242 FFmpegDemuxer::FFmpegDemuxer(MessageLoop* message_loop)
243 : format_context_(NULL), 243 : message_loop_(message_loop),
244 format_context_(NULL),
244 read_event_(false, false), 245 read_event_(false, false),
245 read_has_failed_(false), 246 read_has_failed_(false),
246 last_read_bytes_(0), 247 last_read_bytes_(0),
247 read_position_(0) { 248 read_position_(0) {
249 DCHECK(message_loop_);
248 } 250 }
249 251
250 FFmpegDemuxer::~FFmpegDemuxer() { 252 FFmpegDemuxer::~FFmpegDemuxer() {
251 // In this destructor, we clean up resources held by FFmpeg. It is ugly to 253 // In this destructor, we clean up resources held by FFmpeg. It is ugly to
252 // close the codec contexts here because the corresponding codecs are opened 254 // close the codec contexts here because the corresponding codecs are opened
253 // in the decoder filters. By reaching this point, all filters should have 255 // in the decoder filters. By reaching this point, all filters should have
254 // stopped, so this is the only safe place to do the global clean up. 256 // stopped, so this is the only safe place to do the global clean up.
255 // TODO(hclam): close the codecs in the corresponding decoders. 257 // TODO(hclam): close the codecs in the corresponding decoders.
256 if (!format_context_) 258 if (!format_context_)
257 return; 259 return;
(...skipping 14 matching lines...) Expand all
272 avcodec_close(stream->codec); 274 avcodec_close(stream->codec);
273 } 275 }
274 } 276 }
275 277
276 // Then finally cleanup the format context. 278 // Then finally cleanup the format context.
277 av_close_input_file(format_context_); 279 av_close_input_file(format_context_);
278 format_context_ = NULL; 280 format_context_ = NULL;
279 } 281 }
280 282
281 void FFmpegDemuxer::PostDemuxTask() { 283 void FFmpegDemuxer::PostDemuxTask() {
282 message_loop()->PostTask(FROM_HERE, 284 message_loop_->PostTask(FROM_HERE,
283 NewRunnableMethod(this, &FFmpegDemuxer::DemuxTask)); 285 NewRunnableMethod(this, &FFmpegDemuxer::DemuxTask));
284 } 286 }
285 287
286 void FFmpegDemuxer::Stop(FilterCallback* callback) { 288 void FFmpegDemuxer::Stop(FilterCallback* callback) {
287 // Post a task to notify the streams to stop as well. 289 // Post a task to notify the streams to stop as well.
288 message_loop()->PostTask(FROM_HERE, 290 message_loop_->PostTask(FROM_HERE,
289 NewRunnableMethod(this, &FFmpegDemuxer::StopTask, callback)); 291 NewRunnableMethod(this, &FFmpegDemuxer::StopTask, callback));
290 292
291 // Then wakes up the thread from reading. 293 // Then wakes up the thread from reading.
292 SignalReadCompleted(DataSource::kReadError); 294 SignalReadCompleted(DataSource::kReadError);
293 } 295 }
294 296
295 void FFmpegDemuxer::Seek(base::TimeDelta time, FilterCallback* callback) { 297 void FFmpegDemuxer::Seek(base::TimeDelta time, FilterCallback* callback) {
296 // TODO(hclam): by returning from this method, it is assumed that the seek 298 // TODO(hclam): by returning from this method, it is assumed that the seek
297 // operation is completed and filters behind the demuxer is good to issue 299 // operation is completed and filters behind the demuxer is good to issue
298 // more reads, but we are posting a task here, which makes the seek operation 300 // more reads, but we are posting a task here, which makes the seek operation
299 // asynchronous, should change how seek works to make it fully asynchronous. 301 // asynchronous, should change how seek works to make it fully asynchronous.
300 message_loop()->PostTask(FROM_HERE, 302 message_loop_->PostTask(FROM_HERE,
301 NewRunnableMethod(this, &FFmpegDemuxer::SeekTask, time, callback)); 303 NewRunnableMethod(this, &FFmpegDemuxer::SeekTask, time, callback));
302 } 304 }
303 305
304 void FFmpegDemuxer::OnAudioRendererDisabled() { 306 void FFmpegDemuxer::OnAudioRendererDisabled() {
305 message_loop()->PostTask(FROM_HERE, 307 message_loop_->PostTask(FROM_HERE,
306 NewRunnableMethod(this, &FFmpegDemuxer::DisableAudioStreamTask)); 308 NewRunnableMethod(this, &FFmpegDemuxer::DisableAudioStreamTask));
307 } 309 }
308 310
309 void FFmpegDemuxer::Initialize(DataSource* data_source, 311 void FFmpegDemuxer::Initialize(DataSource* data_source,
310 FilterCallback* callback) { 312 FilterCallback* callback) {
311 message_loop()->PostTask( 313 message_loop_->PostTask(
312 FROM_HERE, 314 FROM_HERE,
313 NewRunnableMethod(this, 315 NewRunnableMethod(this,
314 &FFmpegDemuxer::InitializeTask, 316 &FFmpegDemuxer::InitializeTask,
315 make_scoped_refptr(data_source), 317 make_scoped_refptr(data_source),
316 callback)); 318 callback));
317 } 319 }
318 320
319 size_t FFmpegDemuxer::GetNumberOfStreams() { 321 size_t FFmpegDemuxer::GetNumberOfStreams() {
320 return streams_.size(); 322 return streams_.size();
321 } 323 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 386
385 return data_source_->GetSize(size_out); 387 return data_source_->GetSize(size_out);
386 } 388 }
387 389
388 bool FFmpegDemuxer::IsStreaming() { 390 bool FFmpegDemuxer::IsStreaming() {
389 DCHECK(data_source_); 391 DCHECK(data_source_);
390 392
391 return data_source_->IsStreaming(); 393 return data_source_->IsStreaming();
392 } 394 }
393 395
396 MessageLoop* FFmpegDemuxer::message_loop() {
397 return message_loop_;
398 }
399
394 void FFmpegDemuxer::InitializeTask(DataSource* data_source, 400 void FFmpegDemuxer::InitializeTask(DataSource* data_source,
395 FilterCallback* callback) { 401 FilterCallback* callback) {
396 DCHECK_EQ(MessageLoop::current(), message_loop()); 402 DCHECK_EQ(MessageLoop::current(), message_loop_);
397 scoped_ptr<FilterCallback> c(callback); 403 scoped_ptr<FilterCallback> c(callback);
398 404
399 data_source_ = data_source; 405 data_source_ = data_source;
400 406
401 // Add ourself to Protocol list and get our unique key. 407 // Add ourself to Protocol list and get our unique key.
402 std::string key = FFmpegGlue::GetInstance()->AddProtocol(this); 408 std::string key = FFmpegGlue::GetInstance()->AddProtocol(this);
403 409
404 // Open FFmpeg AVFormatContext. 410 // Open FFmpeg AVFormatContext.
405 DCHECK(!format_context_); 411 DCHECK(!format_context_);
406 AVFormatContext* context = NULL; 412 AVFormatContext* context = NULL;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 max_duration = base::TimeDelta::FromMicroseconds( 476 max_duration = base::TimeDelta::FromMicroseconds(
471 Limits::kMaxTimeInMicroseconds); 477 Limits::kMaxTimeInMicroseconds);
472 } 478 }
473 479
474 // Good to go: set the duration and notify we're done initializing. 480 // Good to go: set the duration and notify we're done initializing.
475 host()->SetDuration(max_duration); 481 host()->SetDuration(max_duration);
476 callback->Run(); 482 callback->Run();
477 } 483 }
478 484
479 void FFmpegDemuxer::SeekTask(base::TimeDelta time, FilterCallback* callback) { 485 void FFmpegDemuxer::SeekTask(base::TimeDelta time, FilterCallback* callback) {
480 DCHECK_EQ(MessageLoop::current(), message_loop()); 486 DCHECK_EQ(MessageLoop::current(), message_loop_);
481 scoped_ptr<FilterCallback> c(callback); 487 scoped_ptr<FilterCallback> c(callback);
482 488
483 // Tell streams to flush buffers due to seeking. 489 // Tell streams to flush buffers due to seeking.
484 StreamVector::iterator iter; 490 StreamVector::iterator iter;
485 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { 491 for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
486 (*iter)->FlushBuffers(); 492 (*iter)->FlushBuffers();
487 } 493 }
488 494
489 // Always seek to a timestamp less than or equal to the desired timestamp. 495 // Always seek to a timestamp less than or equal to the desired timestamp.
490 int flags = AVSEEK_FLAG_BACKWARD; 496 int flags = AVSEEK_FLAG_BACKWARD;
491 497
492 // Passing -1 as our stream index lets FFmpeg pick a default stream. FFmpeg 498 // Passing -1 as our stream index lets FFmpeg pick a default stream. FFmpeg
493 // will attempt to use the lowest-index video stream, if present, followed by 499 // will attempt to use the lowest-index video stream, if present, followed by
494 // the lowest-index audio stream. 500 // the lowest-index audio stream.
495 if (av_seek_frame(format_context_, -1, time.InMicroseconds(), flags) < 0) { 501 if (av_seek_frame(format_context_, -1, time.InMicroseconds(), flags) < 0) {
496 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being 502 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being
497 // captured from stdout and contaminates testing. 503 // captured from stdout and contaminates testing.
498 // TODO(scherkus): Implement this properly and signal error (BUG=23447). 504 // TODO(scherkus): Implement this properly and signal error (BUG=23447).
499 VLOG(1) << "Not implemented"; 505 VLOG(1) << "Not implemented";
500 } 506 }
501 507
502 // Notify we're finished seeking. 508 // Notify we're finished seeking.
503 callback->Run(); 509 callback->Run();
504 } 510 }
505 511
506 void FFmpegDemuxer::DemuxTask() { 512 void FFmpegDemuxer::DemuxTask() {
507 DCHECK_EQ(MessageLoop::current(), message_loop()); 513 DCHECK_EQ(MessageLoop::current(), message_loop_);
508 514
509 // Make sure we have work to do before demuxing. 515 // Make sure we have work to do before demuxing.
510 if (!StreamsHavePendingReads()) { 516 if (!StreamsHavePendingReads()) {
511 return; 517 return;
512 } 518 }
513 519
514 // Allocate and read an AVPacket from the media. 520 // Allocate and read an AVPacket from the media.
515 scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet(new AVPacket()); 521 scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet(new AVPacket());
516 int result = av_read_frame(format_context_, packet.get()); 522 int result = av_read_frame(format_context_, packet.get());
517 if (result < 0) { 523 if (result < 0) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 } 555 }
550 556
551 // Create a loop by posting another task. This allows seek and message loop 557 // Create a loop by posting another task. This allows seek and message loop
552 // quit tasks to get processed. 558 // quit tasks to get processed.
553 if (StreamsHavePendingReads()) { 559 if (StreamsHavePendingReads()) {
554 PostDemuxTask(); 560 PostDemuxTask();
555 } 561 }
556 } 562 }
557 563
558 void FFmpegDemuxer::StopTask(FilterCallback* callback) { 564 void FFmpegDemuxer::StopTask(FilterCallback* callback) {
559 DCHECK_EQ(MessageLoop::current(), message_loop()); 565 DCHECK_EQ(MessageLoop::current(), message_loop_);
560 StreamVector::iterator iter; 566 StreamVector::iterator iter;
561 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { 567 for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
562 (*iter)->Stop(); 568 (*iter)->Stop();
563 } 569 }
564 if (callback) { 570 if (callback) {
565 callback->Run(); 571 callback->Run();
566 delete callback; 572 delete callback;
567 } 573 }
568 } 574 }
569 575
570 void FFmpegDemuxer::DisableAudioStreamTask() { 576 void FFmpegDemuxer::DisableAudioStreamTask() {
571 DCHECK_EQ(MessageLoop::current(), message_loop()); 577 DCHECK_EQ(MessageLoop::current(), message_loop_);
572 578
573 StreamVector::iterator iter; 579 StreamVector::iterator iter;
574 for (size_t i = 0; i < packet_streams_.size(); ++i) { 580 for (size_t i = 0; i < packet_streams_.size(); ++i) {
575 if (!packet_streams_[i]) 581 if (!packet_streams_[i])
576 continue; 582 continue;
577 583
578 // If the codec type is audio, remove the reference. DemuxTask() will 584 // If the codec type is audio, remove the reference. DemuxTask() will
579 // look for such reference, and this will result in deleting the 585 // look for such reference, and this will result in deleting the
580 // audio packets after they are demuxed. 586 // audio packets after they are demuxed.
581 if (packet_streams_[i]->GetAVStream()->codec->codec_type == 587 if (packet_streams_[i]->GetAVStream()->codec->codec_type ==
582 CODEC_TYPE_AUDIO) { 588 CODEC_TYPE_AUDIO) {
583 packet_streams_[i] = NULL; 589 packet_streams_[i] = NULL;
584 } 590 }
585 } 591 }
586 } 592 }
587 593
588 bool FFmpegDemuxer::StreamsHavePendingReads() { 594 bool FFmpegDemuxer::StreamsHavePendingReads() {
589 DCHECK_EQ(MessageLoop::current(), message_loop()); 595 DCHECK_EQ(MessageLoop::current(), message_loop_);
590 StreamVector::iterator iter; 596 StreamVector::iterator iter;
591 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { 597 for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
592 if ((*iter)->HasPendingReads()) { 598 if ((*iter)->HasPendingReads()) {
593 return true; 599 return true;
594 } 600 }
595 } 601 }
596 return false; 602 return false;
597 } 603 }
598 604
599 void FFmpegDemuxer::StreamHasEnded() { 605 void FFmpegDemuxer::StreamHasEnded() {
600 DCHECK_EQ(MessageLoop::current(), message_loop()); 606 DCHECK_EQ(MessageLoop::current(), message_loop_);
601 StreamVector::iterator iter; 607 StreamVector::iterator iter;
602 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { 608 for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
603 AVPacket* packet = new AVPacket(); 609 AVPacket* packet = new AVPacket();
604 memset(packet, 0, sizeof(*packet)); 610 memset(packet, 0, sizeof(*packet));
605 (*iter)->EnqueuePacket(packet); 611 (*iter)->EnqueuePacket(packet);
606 } 612 }
607 } 613 }
608 614
609 void FFmpegDemuxer::OnReadCompleted(size_t size) { 615 void FFmpegDemuxer::OnReadCompleted(size_t size) {
610 SignalReadCompleted(size); 616 SignalReadCompleted(size);
611 } 617 }
612 618
613 size_t FFmpegDemuxer::WaitForRead() { 619 size_t FFmpegDemuxer::WaitForRead() {
614 read_event_.Wait(); 620 read_event_.Wait();
615 return last_read_bytes_; 621 return last_read_bytes_;
616 } 622 }
617 623
618 void FFmpegDemuxer::SignalReadCompleted(size_t size) { 624 void FFmpegDemuxer::SignalReadCompleted(size_t size) {
619 last_read_bytes_ = size; 625 last_read_bytes_ = size;
620 read_event_.Signal(); 626 read_event_.Signal();
621 } 627 }
622 628
623 } // namespace media 629 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | media/filters/ffmpeg_demuxer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698