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

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

Issue 193303002: WeakPtr destruction order cleanup: media edition. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase. Created 6 years, 9 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_video_decoder.h » ('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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "media/filters/ffmpeg_demuxer.h" 5 #include "media/filters/ffmpeg_demuxer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/base64.h" 10 #include "base/base64.h"
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 // 362 //
363 // FFmpegDemuxer 363 // FFmpegDemuxer
364 // 364 //
365 FFmpegDemuxer::FFmpegDemuxer( 365 FFmpegDemuxer::FFmpegDemuxer(
366 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 366 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
367 DataSource* data_source, 367 DataSource* data_source,
368 const NeedKeyCB& need_key_cb, 368 const NeedKeyCB& need_key_cb,
369 const scoped_refptr<MediaLog>& media_log) 369 const scoped_refptr<MediaLog>& media_log)
370 : host_(NULL), 370 : host_(NULL),
371 task_runner_(task_runner), 371 task_runner_(task_runner),
372 weak_factory_(this),
373 blocking_thread_("FFmpegDemuxer"), 372 blocking_thread_("FFmpegDemuxer"),
374 pending_read_(false), 373 pending_read_(false),
375 pending_seek_(false), 374 pending_seek_(false),
376 data_source_(data_source), 375 data_source_(data_source),
377 media_log_(media_log), 376 media_log_(media_log),
378 bitrate_(0), 377 bitrate_(0),
379 start_time_(kNoTimestamp()), 378 start_time_(kNoTimestamp()),
380 audio_disabled_(false), 379 audio_disabled_(false),
381 text_enabled_(false), 380 text_enabled_(false),
382 duration_known_(false), 381 duration_known_(false),
383 need_key_cb_(need_key_cb) { 382 need_key_cb_(need_key_cb),
383 weak_factory_(this) {
384 DCHECK(task_runner_.get()); 384 DCHECK(task_runner_.get());
385 DCHECK(data_source_); 385 DCHECK(data_source_);
386 } 386 }
387 387
388 FFmpegDemuxer::~FFmpegDemuxer() {} 388 FFmpegDemuxer::~FFmpegDemuxer() {}
389 389
390 void FFmpegDemuxer::Stop(const base::Closure& callback) { 390 void FFmpegDemuxer::Stop(const base::Closure& callback) {
391 DCHECK(task_runner_->BelongsToCurrentThread()); 391 DCHECK(task_runner_->BelongsToCurrentThread());
392 url_protocol_->Abort(); 392 url_protocol_->Abort();
393 data_source_->Stop(BindToCurrentLoop(base::Bind( 393 data_source_->Stop(
394 &FFmpegDemuxer::OnDataSourceStopped, weak_this_, 394 BindToCurrentLoop(base::Bind(&FFmpegDemuxer::OnDataSourceStopped,
395 BindToCurrentLoop(callback)))); 395 weak_factory_.GetWeakPtr(),
396 BindToCurrentLoop(callback))));
396 data_source_ = NULL; 397 data_source_ = NULL;
397 } 398 }
398 399
399 void FFmpegDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) { 400 void FFmpegDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) {
400 DCHECK(task_runner_->BelongsToCurrentThread()); 401 DCHECK(task_runner_->BelongsToCurrentThread());
401 CHECK(!pending_seek_); 402 CHECK(!pending_seek_);
402 403
403 // TODO(scherkus): Inspect |pending_read_| and cancel IO via |blocking_url_|, 404 // TODO(scherkus): Inspect |pending_read_| and cancel IO via |blocking_url_|,
404 // otherwise we can end up waiting for a pre-seek read to complete even though 405 // otherwise we can end up waiting for a pre-seek read to complete even though
405 // we know we're going to drop it on the floor. 406 // we know we're going to drop it on the floor.
406 407
407 // Always seek to a timestamp less than or equal to the desired timestamp. 408 // Always seek to a timestamp less than or equal to the desired timestamp.
408 int flags = AVSEEK_FLAG_BACKWARD; 409 int flags = AVSEEK_FLAG_BACKWARD;
409 410
410 // Passing -1 as our stream index lets FFmpeg pick a default stream. FFmpeg 411 // Passing -1 as our stream index lets FFmpeg pick a default stream. FFmpeg
411 // will attempt to use the lowest-index video stream, if present, followed by 412 // will attempt to use the lowest-index video stream, if present, followed by
412 // the lowest-index audio stream. 413 // the lowest-index audio stream.
413 pending_seek_ = true; 414 pending_seek_ = true;
414 base::PostTaskAndReplyWithResult( 415 base::PostTaskAndReplyWithResult(
415 blocking_thread_.message_loop_proxy().get(), 416 blocking_thread_.message_loop_proxy().get(),
416 FROM_HERE, 417 FROM_HERE,
417 base::Bind(&av_seek_frame, 418 base::Bind(&av_seek_frame,
418 glue_->format_context(), 419 glue_->format_context(),
419 -1, 420 -1,
420 time.InMicroseconds(), 421 time.InMicroseconds(),
421 flags), 422 flags),
422 base::Bind(&FFmpegDemuxer::OnSeekFrameDone, weak_this_, cb)); 423 base::Bind(
424 &FFmpegDemuxer::OnSeekFrameDone, weak_factory_.GetWeakPtr(), cb));
423 } 425 }
424 426
425 void FFmpegDemuxer::OnAudioRendererDisabled() { 427 void FFmpegDemuxer::OnAudioRendererDisabled() {
426 DCHECK(task_runner_->BelongsToCurrentThread()); 428 DCHECK(task_runner_->BelongsToCurrentThread());
427 audio_disabled_ = true; 429 audio_disabled_ = true;
428 StreamVector::iterator iter; 430 StreamVector::iterator iter;
429 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { 431 for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
430 if (*iter && (*iter)->type() == DemuxerStream::AUDIO) { 432 if (*iter && (*iter)->type() == DemuxerStream::AUDIO) {
431 (*iter)->Stop(); 433 (*iter)->Stop();
432 } 434 }
433 } 435 }
434 } 436 }
435 437
436 void FFmpegDemuxer::Initialize(DemuxerHost* host, 438 void FFmpegDemuxer::Initialize(DemuxerHost* host,
437 const PipelineStatusCB& status_cb, 439 const PipelineStatusCB& status_cb,
438 bool enable_text_tracks) { 440 bool enable_text_tracks) {
439 DCHECK(task_runner_->BelongsToCurrentThread()); 441 DCHECK(task_runner_->BelongsToCurrentThread());
440 host_ = host; 442 host_ = host;
441 weak_this_ = weak_factory_.GetWeakPtr();
442 text_enabled_ = enable_text_tracks; 443 text_enabled_ = enable_text_tracks;
443 444
444 // TODO(scherkus): DataSource should have a host by this point, 445 // TODO(scherkus): DataSource should have a host by this point,
445 // see http://crbug.com/122071 446 // see http://crbug.com/122071
446 data_source_->set_host(host); 447 data_source_->set_host(host);
447 448
448 url_protocol_.reset(new BlockingUrlProtocol(data_source_, BindToCurrentLoop( 449 url_protocol_.reset(new BlockingUrlProtocol(data_source_, BindToCurrentLoop(
449 base::Bind(&FFmpegDemuxer::OnDataSourceError, base::Unretained(this))))); 450 base::Bind(&FFmpegDemuxer::OnDataSourceError, base::Unretained(this)))));
450 glue_.reset(new FFmpegGlue(url_protocol_.get())); 451 glue_.reset(new FFmpegGlue(url_protocol_.get()));
451 AVFormatContext* format_context = glue_->format_context(); 452 AVFormatContext* format_context = glue_->format_context();
452 453
453 // Disable ID3v1 tag reading to avoid costly seeks to end of file for data we 454 // Disable ID3v1 tag reading to avoid costly seeks to end of file for data we
454 // don't use. FFmpeg will only read ID3v1 tags if no other metadata is 455 // don't use. FFmpeg will only read ID3v1 tags if no other metadata is
455 // available, so add a metadata entry to ensure some is always present. 456 // available, so add a metadata entry to ensure some is always present.
456 av_dict_set(&format_context->metadata, "skip_id3v1_tags", "", 0); 457 av_dict_set(&format_context->metadata, "skip_id3v1_tags", "", 0);
457 458
458 // Open the AVFormatContext using our glue layer. 459 // Open the AVFormatContext using our glue layer.
459 CHECK(blocking_thread_.Start()); 460 CHECK(blocking_thread_.Start());
460 base::PostTaskAndReplyWithResult( 461 base::PostTaskAndReplyWithResult(
461 blocking_thread_.message_loop_proxy().get(), 462 blocking_thread_.message_loop_proxy().get(),
462 FROM_HERE, 463 FROM_HERE,
463 base::Bind(&FFmpegGlue::OpenContext, base::Unretained(glue_.get())), 464 base::Bind(&FFmpegGlue::OpenContext, base::Unretained(glue_.get())),
464 base::Bind(&FFmpegDemuxer::OnOpenContextDone, weak_this_, status_cb)); 465 base::Bind(&FFmpegDemuxer::OnOpenContextDone,
466 weak_factory_.GetWeakPtr(),
467 status_cb));
465 } 468 }
466 469
467 DemuxerStream* FFmpegDemuxer::GetStream(DemuxerStream::Type type) { 470 DemuxerStream* FFmpegDemuxer::GetStream(DemuxerStream::Type type) {
468 DCHECK(task_runner_->BelongsToCurrentThread()); 471 DCHECK(task_runner_->BelongsToCurrentThread());
469 return GetFFmpegStream(type); 472 return GetFFmpegStream(type);
470 } 473 }
471 474
472 FFmpegDemuxerStream* FFmpegDemuxer::GetFFmpegStream( 475 FFmpegDemuxerStream* FFmpegDemuxer::GetFFmpegStream(
473 DemuxerStream::Type type) const { 476 DemuxerStream::Type type) const {
474 StreamVector::const_iterator iter; 477 StreamVector::const_iterator iter;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 return; 556 return;
554 } 557 }
555 558
556 // Fully initialize AVFormatContext by parsing the stream a little. 559 // Fully initialize AVFormatContext by parsing the stream a little.
557 base::PostTaskAndReplyWithResult( 560 base::PostTaskAndReplyWithResult(
558 blocking_thread_.message_loop_proxy().get(), 561 blocking_thread_.message_loop_proxy().get(),
559 FROM_HERE, 562 FROM_HERE,
560 base::Bind(&avformat_find_stream_info, 563 base::Bind(&avformat_find_stream_info,
561 glue_->format_context(), 564 glue_->format_context(),
562 static_cast<AVDictionary**>(NULL)), 565 static_cast<AVDictionary**>(NULL)),
563 base::Bind(&FFmpegDemuxer::OnFindStreamInfoDone, weak_this_, status_cb)); 566 base::Bind(&FFmpegDemuxer::OnFindStreamInfoDone,
567 weak_factory_.GetWeakPtr(),
568 status_cb));
564 } 569 }
565 570
566 void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb, 571 void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
567 int result) { 572 int result) {
568 DCHECK(task_runner_->BelongsToCurrentThread()); 573 DCHECK(task_runner_->BelongsToCurrentThread());
569 if (!blocking_thread_.IsRunning() || !data_source_) { 574 if (!blocking_thread_.IsRunning() || !data_source_) {
570 status_cb.Run(PIPELINE_ERROR_ABORT); 575 status_cb.Run(PIPELINE_ERROR_ABORT);
571 return; 576 return;
572 } 577 }
573 578
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 // evaluation order of packet.get() and base::Passed(&packet) is 791 // evaluation order of packet.get() and base::Passed(&packet) is
787 // undefined. 792 // undefined.
788 ScopedAVPacket packet(new AVPacket()); 793 ScopedAVPacket packet(new AVPacket());
789 AVPacket* packet_ptr = packet.get(); 794 AVPacket* packet_ptr = packet.get();
790 795
791 pending_read_ = true; 796 pending_read_ = true;
792 base::PostTaskAndReplyWithResult( 797 base::PostTaskAndReplyWithResult(
793 blocking_thread_.message_loop_proxy().get(), 798 blocking_thread_.message_loop_proxy().get(),
794 FROM_HERE, 799 FROM_HERE,
795 base::Bind(&av_read_frame, glue_->format_context(), packet_ptr), 800 base::Bind(&av_read_frame, glue_->format_context(), packet_ptr),
796 base::Bind( 801 base::Bind(&FFmpegDemuxer::OnReadFrameDone,
797 &FFmpegDemuxer::OnReadFrameDone, weak_this_, base::Passed(&packet))); 802 weak_factory_.GetWeakPtr(),
803 base::Passed(&packet)));
798 } 804 }
799 805
800 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { 806 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) {
801 DCHECK(task_runner_->BelongsToCurrentThread()); 807 DCHECK(task_runner_->BelongsToCurrentThread());
802 DCHECK(pending_read_); 808 DCHECK(pending_read_);
803 pending_read_ = false; 809 pending_read_ = false;
804 810
805 if (!blocking_thread_.IsRunning() || pending_seek_) { 811 if (!blocking_thread_.IsRunning() || pending_seek_) {
806 return; 812 return;
807 } 813 }
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
976 } 982 }
977 for (size_t i = 0; i < buffered.size(); ++i) 983 for (size_t i = 0; i < buffered.size(); ++i)
978 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); 984 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i));
979 } 985 }
980 986
981 void FFmpegDemuxer::OnDataSourceError() { 987 void FFmpegDemuxer::OnDataSourceError() {
982 host_->OnDemuxerError(PIPELINE_ERROR_READ); 988 host_->OnDemuxerError(PIPELINE_ERROR_READ);
983 } 989 }
984 990
985 } // namespace media 991 } // namespace media
OLDNEW
« 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