OLD | NEW |
---|---|
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/bind.h" | 10 #include "base/bind.h" |
(...skipping 12 matching lines...) Expand all Loading... | |
23 #include "media/ffmpeg/ffmpeg_common.h" | 23 #include "media/ffmpeg/ffmpeg_common.h" |
24 #include "media/filters/bitstream_converter.h" | 24 #include "media/filters/bitstream_converter.h" |
25 #include "media/filters/ffmpeg_glue.h" | 25 #include "media/filters/ffmpeg_glue.h" |
26 #include "media/filters/ffmpeg_h264_bitstream_converter.h" | 26 #include "media/filters/ffmpeg_h264_bitstream_converter.h" |
27 | 27 |
28 namespace media { | 28 namespace media { |
29 | 29 |
30 // | 30 // |
31 // FFmpegDemuxerStream | 31 // FFmpegDemuxerStream |
32 // | 32 // |
33 FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, | 33 FFmpegDemuxerStream::FFmpegDemuxerStream( |
34 AVStream* stream) | 34 const NotifyBufferedCB& notify_buffered_cb, |
35 : demuxer_(demuxer), | 35 FFmpegDemuxer* demuxer, |
36 AVStream* stream) | |
37 : notify_buffered_cb_(notify_buffered_cb), | |
38 demuxer_(demuxer), | |
36 stream_(stream), | 39 stream_(stream), |
37 type_(UNKNOWN), | 40 type_(UNKNOWN), |
38 discontinuous_(false), | 41 discontinuous_(false), |
39 stopped_(false) { | 42 stopped_(false), |
43 last_packet_timestamp_(kNoTimestamp()) { | |
40 DCHECK(demuxer_); | 44 DCHECK(demuxer_); |
41 | 45 |
42 // Determine our media format. | 46 // Determine our media format. |
43 switch (stream->codec->codec_type) { | 47 switch (stream->codec->codec_type) { |
44 case AVMEDIA_TYPE_AUDIO: | 48 case AVMEDIA_TYPE_AUDIO: |
45 type_ = AUDIO; | 49 type_ = AUDIO; |
46 AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_); | 50 AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_); |
47 break; | 51 break; |
48 case AVMEDIA_TYPE_VIDEO: | 52 case AVMEDIA_TYPE_VIDEO: |
49 type_ = VIDEO; | 53 type_ = VIDEO; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
87 } | 91 } |
88 | 92 |
89 // If a packet is returned by FFmpeg's av_parser_parse2() the packet will | 93 // If a packet is returned by FFmpeg's av_parser_parse2() the packet will |
90 // reference inner memory of FFmpeg. As such we should transfer the packet | 94 // reference inner memory of FFmpeg. As such we should transfer the packet |
91 // into memory we control. | 95 // into memory we control. |
92 buffer = DecoderBuffer::CopyFrom(packet->data, packet->size); | 96 buffer = DecoderBuffer::CopyFrom(packet->data, packet->size); |
93 buffer->SetTimestamp(ConvertStreamTimestamp( | 97 buffer->SetTimestamp(ConvertStreamTimestamp( |
94 stream_->time_base, packet->pts)); | 98 stream_->time_base, packet->pts)); |
95 buffer->SetDuration(ConvertStreamTimestamp( | 99 buffer->SetDuration(ConvertStreamTimestamp( |
96 stream_->time_base, packet->duration)); | 100 stream_->time_base, packet->duration)); |
101 if (last_packet_timestamp_ != kNoTimestamp() && | |
102 last_packet_timestamp_ < buffer->GetTimestamp()) { | |
103 notify_buffered_cb_.Run(last_packet_timestamp_, buffer->GetTimestamp()); | |
104 } | |
105 last_packet_timestamp_ = buffer->GetTimestamp(); | |
97 } | 106 } |
98 | 107 |
99 buffer_queue_.push_back(buffer); | 108 buffer_queue_.push_back(buffer); |
100 FulfillPendingRead(); | 109 FulfillPendingRead(); |
101 return; | 110 return; |
102 } | 111 } |
103 | 112 |
104 void FFmpegDemuxerStream::FlushBuffers() { | 113 void FFmpegDemuxerStream::FlushBuffers() { |
105 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); | 114 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); |
106 base::AutoLock auto_lock(lock_); | 115 base::AutoLock auto_lock(lock_); |
107 DCHECK(read_queue_.empty()) << "Read requests should be empty"; | 116 DCHECK(read_queue_.empty()) << "Read requests should be empty"; |
108 buffer_queue_.clear(); | 117 buffer_queue_.clear(); |
118 last_packet_timestamp_ = kNoTimestamp(); | |
109 } | 119 } |
110 | 120 |
111 void FFmpegDemuxerStream::Stop() { | 121 void FFmpegDemuxerStream::Stop() { |
112 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); | 122 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); |
113 base::AutoLock auto_lock(lock_); | 123 base::AutoLock auto_lock(lock_); |
114 buffer_queue_.clear(); | 124 buffer_queue_.clear(); |
115 for (ReadQueue::iterator it = read_queue_.begin(); | 125 for (ReadQueue::iterator it = read_queue_.begin(); |
116 it != read_queue_.end(); ++it) { | 126 it != read_queue_.end(); ++it) { |
117 it->Run(scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer())); | 127 it->Run(scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer())); |
118 } | 128 } |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
472 | 482 |
473 // Fully initialize AVFormatContext by parsing the stream a little. | 483 // Fully initialize AVFormatContext by parsing the stream a little. |
474 result = avformat_find_stream_info(format_context_, NULL); | 484 result = avformat_find_stream_info(format_context_, NULL); |
475 if (result < 0) { | 485 if (result < 0) { |
476 status_cb.Run(DEMUXER_ERROR_COULD_NOT_PARSE); | 486 status_cb.Run(DEMUXER_ERROR_COULD_NOT_PARSE); |
477 return; | 487 return; |
478 } | 488 } |
479 | 489 |
480 // Create demuxer stream entries for each possible AVStream. | 490 // Create demuxer stream entries for each possible AVStream. |
481 streams_.resize(format_context_->nb_streams); | 491 streams_.resize(format_context_->nb_streams); |
492 buffered_times_.resize(streams_.size()); | |
482 bool found_audio_stream = false; | 493 bool found_audio_stream = false; |
483 bool found_video_stream = false; | 494 bool found_video_stream = false; |
484 | 495 |
485 base::TimeDelta max_duration; | 496 base::TimeDelta max_duration; |
486 for (size_t i = 0; i < format_context_->nb_streams; ++i) { | 497 for (size_t i = 0; i < format_context_->nb_streams; ++i) { |
487 AVCodecContext* codec_context = format_context_->streams[i]->codec; | 498 AVCodecContext* codec_context = format_context_->streams[i]->codec; |
488 AVMediaType codec_type = codec_context->codec_type; | 499 AVMediaType codec_type = codec_context->codec_type; |
489 | 500 |
490 if (codec_type == AVMEDIA_TYPE_AUDIO) { | 501 if (codec_type == AVMEDIA_TYPE_AUDIO) { |
491 if (found_audio_stream) | 502 if (found_audio_stream) |
492 continue; | 503 continue; |
493 // Ensure the codec is supported. | 504 // Ensure the codec is supported. |
494 if (CodecIDToAudioCodec(codec_context->codec_id) == kUnknownAudioCodec) | 505 if (CodecIDToAudioCodec(codec_context->codec_id) == kUnknownAudioCodec) |
495 continue; | 506 continue; |
496 found_audio_stream = true; | 507 found_audio_stream = true; |
497 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { | 508 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { |
498 if (found_video_stream) | 509 if (found_video_stream) |
499 continue; | 510 continue; |
500 // Ensure the codec is supported. | 511 // Ensure the codec is supported. |
501 if (CodecIDToVideoCodec(codec_context->codec_id) == kUnknownVideoCodec) | 512 if (CodecIDToVideoCodec(codec_context->codec_id) == kUnknownVideoCodec) |
502 continue; | 513 continue; |
503 found_video_stream = true; | 514 found_video_stream = true; |
504 } else { | 515 } else { |
505 continue; | 516 continue; |
506 } | 517 } |
507 | 518 |
508 AVStream* stream = format_context_->streams[i]; | 519 AVStream* stream = format_context_->streams[i]; |
509 scoped_refptr<FFmpegDemuxerStream> demuxer_stream( | 520 scoped_refptr<FFmpegDemuxerStream> demuxer_stream( |
510 new FFmpegDemuxerStream(this, stream)); | 521 new FFmpegDemuxerStream( |
522 base::Bind(&FFmpegDemuxer::NotifyBufferedRange, this, i), | |
523 this, stream)); | |
511 | 524 |
512 streams_[i] = demuxer_stream; | 525 streams_[i] = demuxer_stream; |
513 max_duration = std::max(max_duration, demuxer_stream->duration()); | 526 max_duration = std::max(max_duration, demuxer_stream->duration()); |
514 | 527 |
515 if (stream->first_dts != static_cast<int64_t>(AV_NOPTS_VALUE)) { | 528 if (stream->first_dts != static_cast<int64_t>(AV_NOPTS_VALUE)) { |
516 const base::TimeDelta first_dts = ConvertFromTimeBase( | 529 const base::TimeDelta first_dts = ConvertFromTimeBase( |
517 stream->time_base, stream->first_dts); | 530 stream->time_base, stream->first_dts); |
518 if (start_time_ == kNoTimestamp() || first_dts < start_time_) | 531 if (start_time_ == kNoTimestamp() || first_dts < start_time_) |
519 start_time_ = first_dts; | 532 start_time_ = first_dts; |
520 } | 533 } |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
700 int FFmpegDemuxer::WaitForRead() { | 713 int FFmpegDemuxer::WaitForRead() { |
701 read_event_.Wait(); | 714 read_event_.Wait(); |
702 return last_read_bytes_; | 715 return last_read_bytes_; |
703 } | 716 } |
704 | 717 |
705 void FFmpegDemuxer::SignalReadCompleted(int size) { | 718 void FFmpegDemuxer::SignalReadCompleted(int size) { |
706 last_read_bytes_ = size; | 719 last_read_bytes_ = size; |
707 read_event_.Signal(); | 720 read_event_.Signal(); |
708 } | 721 } |
709 | 722 |
723 void FFmpegDemuxer::NotifyBufferedRange( | |
724 int stream_id, base::TimeDelta start, base::TimeDelta end) { | |
725 buffered_times_[stream_id].Add(start, end); | |
scherkus (not reviewing)
2012/06/22 06:13:51
I think each FDS stream should hold onto its own r
Ami GONE FROM CHROMIUM
2012/06/22 17:15:32
Done.
| |
726 | |
727 Ranges<base::TimeDelta> buffered = buffered_times_[0]; | |
728 for (size_t i = 1; i < streams_.size(); ++i) | |
729 buffered = buffered.IntersectionWith(buffered_times_[i]); | |
730 for (size_t i = 0; i < buffered.size(); ++i) | |
731 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); | |
732 } | |
733 | |
710 } // namespace media | 734 } // namespace media |
OLD | NEW |