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

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

Issue 8890071: Stop audio FFmpegDemuxerStreams if we get notified that audio rendering is disabled. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src
Patch Set: one more time Created 9 years 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/bind.h" 5 #include "base/bind.h"
6 #include "base/callback.h" 6 #include "base/callback.h"
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 it->Run(scoped_refptr<Buffer>(new DataBuffer(0))); 146 it->Run(scoped_refptr<Buffer>(new DataBuffer(0)));
147 } 147 }
148 read_queue_.clear(); 148 read_queue_.clear();
149 stopped_ = true; 149 stopped_ = true;
150 } 150 }
151 151
152 base::TimeDelta FFmpegDemuxerStream::duration() { 152 base::TimeDelta FFmpegDemuxerStream::duration() {
153 return duration_; 153 return duration_;
154 } 154 }
155 155
156 int FFmpegDemuxerStream::stream_index() {
157 return stream_->index;
158 }
159
156 DemuxerStream::Type FFmpegDemuxerStream::type() { 160 DemuxerStream::Type FFmpegDemuxerStream::type() {
157 return type_; 161 return type_;
158 } 162 }
159 163
160 void FFmpegDemuxerStream::Read(const ReadCallback& read_callback) { 164 void FFmpegDemuxerStream::Read(const ReadCallback& read_callback) {
161 DCHECK(!read_callback.is_null()); 165 DCHECK(!read_callback.is_null());
162 166
163 base::AutoLock auto_lock(lock_); 167 base::AutoLock auto_lock(lock_);
164 // Don't accept any additional reads if we've been told to stop. 168 // Don't accept any additional reads if we've been told to stop.
165 // The demuxer_ may have been destroyed in the pipleine thread. 169 // The demuxer_ may have been destroyed in the pipleine thread.
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 streams_.resize(DemuxerStream::NUM_TYPES); 487 streams_.resize(DemuxerStream::NUM_TYPES);
484 base::TimeDelta max_duration; 488 base::TimeDelta max_duration;
485 bool no_supported_streams = true; 489 bool no_supported_streams = true;
486 for (size_t i = 0; i < format_context_->nb_streams; ++i) { 490 for (size_t i = 0; i < format_context_->nb_streams; ++i) {
487 AVCodecContext* codec_context = format_context_->streams[i]->codec; 491 AVCodecContext* codec_context = format_context_->streams[i]->codec;
488 AVMediaType codec_type = codec_context->codec_type; 492 AVMediaType codec_type = codec_context->codec_type;
489 if (codec_type == AVMEDIA_TYPE_AUDIO || codec_type == AVMEDIA_TYPE_VIDEO) { 493 if (codec_type == AVMEDIA_TYPE_AUDIO || codec_type == AVMEDIA_TYPE_VIDEO) {
490 AVStream* stream = format_context_->streams[i]; 494 AVStream* stream = format_context_->streams[i];
491 scoped_refptr<FFmpegDemuxerStream> demuxer_stream( 495 scoped_refptr<FFmpegDemuxerStream> demuxer_stream(
492 new FFmpegDemuxerStream(this, stream)); 496 new FFmpegDemuxerStream(this, stream));
497
493 if (!streams_[demuxer_stream->type()]) { 498 if (!streams_[demuxer_stream->type()]) {
494 no_supported_streams = false; 499 no_supported_streams = false;
495 streams_[demuxer_stream->type()] = demuxer_stream; 500 streams_[demuxer_stream->type()] = demuxer_stream;
496 max_duration = std::max(max_duration, demuxer_stream->duration()); 501 max_duration = std::max(max_duration, demuxer_stream->duration());
497 502
498 if (stream->first_dts != static_cast<int64_t>(AV_NOPTS_VALUE)) { 503 if (stream->first_dts != static_cast<int64_t>(AV_NOPTS_VALUE)) {
499 const base::TimeDelta first_dts = ConvertFromTimeBase( 504 const base::TimeDelta first_dts = ConvertFromTimeBase(
500 stream->time_base, stream->first_dts); 505 stream->time_base, stream->first_dts);
501 if (start_time_ == kNoTimestamp || first_dts < start_time_) 506 if (start_time_ == kNoTimestamp || first_dts < start_time_)
502 start_time_ = first_dts; 507 start_time_ = first_dts;
503 } 508 }
504 } 509 }
505 packet_streams_.push_back(demuxer_stream);
506 } else {
507 packet_streams_.push_back(NULL);
508 } 510 }
509 } 511 }
510 if (no_supported_streams) { 512 if (no_supported_streams) {
511 callback.Run(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); 513 callback.Run(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
512 return; 514 return;
513 } 515 }
514 if (format_context_->duration != static_cast<int64_t>(AV_NOPTS_VALUE)) { 516 if (format_context_->duration != static_cast<int64_t>(AV_NOPTS_VALUE)) {
515 // If there is a duration value in the container use that to find the 517 // If there is a duration value in the container use that to find the
516 // maximum between it and the duration from A/V streams. 518 // maximum between it and the duration from A/V streams.
517 const AVRational av_time_base = {1, AV_TIME_BASE}; 519 const AVRational av_time_base = {1, AV_TIME_BASE};
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 // If we have reached the end of stream, tell the downstream filters about 636 // If we have reached the end of stream, tell the downstream filters about
635 // the event. 637 // the event.
636 StreamHasEnded(); 638 StreamHasEnded();
637 return; 639 return;
638 } 640 }
639 641
640 // Queue the packet with the appropriate stream. 642 // Queue the packet with the appropriate stream.
641 // TODO(scherkus): should we post this back to the pipeline thread? I'm 643 // TODO(scherkus): should we post this back to the pipeline thread? I'm
642 // worried about downstream filters (i.e., decoders) executing on this 644 // worried about downstream filters (i.e., decoders) executing on this
643 // thread. 645 // thread.
644 DCHECK_GE(packet->stream_index, 0); 646 for (StreamVector::iterator iter = streams_.begin();
acolwell GONE FROM CHROMIUM 2011/12/13 16:45:44 I don't feel good about this iteration happening o
scherkus (not reviewing) 2011/12/13 17:24:56 This loop unrolls to checking streams_[AUDIO]->str
645 DCHECK_LT(packet->stream_index, static_cast<int>(packet_streams_.size())); 647 iter != streams_.end();
646 FFmpegDemuxerStream* demuxer_stream = NULL; 648 ++iter) {
647 size_t i = packet->stream_index; 649 if ((*iter) && (*iter)->stream_index() == packet->stream_index) {
648 // Defend against ffmpeg giving us a bad stream index.
649 if (i < packet_streams_.size()) {
650 demuxer_stream = packet_streams_[i];
651 }
652 if (demuxer_stream) {
653 // Queue the packet with the appropriate stream. The stream takes
654 // ownership of the AVPacket.
655 if (packet.get()) {
656 // If a packet is returned by FFmpeg's av_parser_parse2() 650 // If a packet is returned by FFmpeg's av_parser_parse2()
657 // the packet will reference an inner memory of FFmpeg. 651 // the packet will reference an inner memory of FFmpeg.
658 // In this case, the packet's "destruct" member is NULL, 652 // In this case, the packet's "destruct" member is NULL,
659 // and it MUST be duplicated. This fixes issue with MP3 and possibly 653 // and it MUST be duplicated. This fixes issue with MP3 and possibly
660 // other codecs. It is safe to call this function even if the packet does 654 // other codecs. It is safe to call this function even if the packet does
661 // not refer to inner memory from FFmpeg. 655 // not refer to inner memory from FFmpeg.
662 av_dup_packet(packet.get()); 656 av_dup_packet(packet.get());
663 demuxer_stream->EnqueuePacket(packet.release()); 657
658 // Queue the packet with the appropriate stream. The stream takes
659 // ownership of the AVPacket.
660 (*iter)->EnqueuePacket(packet.release());
661 break;
664 } 662 }
665 } 663 }
666 664
667 // Create a loop by posting another task. This allows seek and message loop 665 // Create a loop by posting another task. This allows seek and message loop
668 // quit tasks to get processed. 666 // quit tasks to get processed.
669 if (StreamsHavePendingReads()) { 667 if (StreamsHavePendingReads()) {
670 PostDemuxTask(); 668 PostDemuxTask();
671 } 669 }
672 } 670 }
673 671
674 void FFmpegDemuxer::StopTask(const base::Closure& callback) { 672 void FFmpegDemuxer::StopTask(const base::Closure& callback) {
675 DCHECK_EQ(MessageLoop::current(), message_loop_); 673 DCHECK_EQ(MessageLoop::current(), message_loop_);
676 StreamVector::iterator iter; 674 StreamVector::iterator iter;
677 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { 675 for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
678 if (*iter) 676 if (*iter)
679 (*iter)->Stop(); 677 (*iter)->Stop();
680 } 678 }
681 if (data_source_) { 679 if (data_source_) {
682 data_source_->Stop(callback); 680 data_source_->Stop(callback);
683 } else { 681 } else {
684 callback.Run(); 682 callback.Run();
685 } 683 }
686 } 684 }
687 685
688 void FFmpegDemuxer::DisableAudioStreamTask() { 686 void FFmpegDemuxer::DisableAudioStreamTask() {
689 DCHECK_EQ(MessageLoop::current(), message_loop_); 687 DCHECK_EQ(MessageLoop::current(), message_loop_);
690 688
691 StreamVector::iterator iter; 689 if (streams_[DemuxerStream::AUDIO]) {
692 for (size_t i = 0; i < packet_streams_.size(); ++i) { 690 streams_[DemuxerStream::AUDIO]->Stop();
693 if (!packet_streams_[i])
694 continue;
695
696 // If the codec type is audio, remove the reference. DemuxTask() will
697 // look for such reference, and this will result in deleting the
698 // audio packets after they are demuxed.
699 if (packet_streams_[i]->type() == DemuxerStream::AUDIO) {
700 packet_streams_[i] = NULL;
701 }
702 } 691 }
703 } 692 }
704 693
705 bool FFmpegDemuxer::StreamsHavePendingReads() { 694 bool FFmpegDemuxer::StreamsHavePendingReads() {
706 DCHECK_EQ(MessageLoop::current(), message_loop_); 695 DCHECK_EQ(MessageLoop::current(), message_loop_);
707 StreamVector::iterator iter; 696 StreamVector::iterator iter;
708 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { 697 for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
709 if (*iter && (*iter)->HasPendingReads()) { 698 if (*iter && (*iter)->HasPendingReads()) {
710 return true; 699 return true;
711 } 700 }
(...skipping 21 matching lines...) Expand all
733 read_event_.Wait(); 722 read_event_.Wait();
734 return last_read_bytes_; 723 return last_read_bytes_;
735 } 724 }
736 725
737 void FFmpegDemuxer::SignalReadCompleted(size_t size) { 726 void FFmpegDemuxer::SignalReadCompleted(size_t size) {
738 last_read_bytes_ = size; 727 last_read_bytes_ = size;
739 read_event_.Signal(); 728 read_event_.Signal();
740 } 729 }
741 730
742 } // namespace media 731 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698