| OLD | NEW |
| 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/callback.h" | 5 #include "base/callback.h" |
| 6 #include "base/command_line.h" | 6 #include "base/command_line.h" |
| 7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 AVStream* stream) | 58 AVStream* stream) |
| 59 : demuxer_(demuxer), | 59 : demuxer_(demuxer), |
| 60 stream_(stream), | 60 stream_(stream), |
| 61 type_(UNKNOWN), | 61 type_(UNKNOWN), |
| 62 discontinuous_(false), | 62 discontinuous_(false), |
| 63 stopped_(false) { | 63 stopped_(false) { |
| 64 DCHECK(demuxer_); | 64 DCHECK(demuxer_); |
| 65 | 65 |
| 66 // Determine our media format. | 66 // Determine our media format. |
| 67 switch (stream->codec->codec_type) { | 67 switch (stream->codec->codec_type) { |
| 68 case CODEC_TYPE_AUDIO: | 68 case AVMEDIA_TYPE_AUDIO: |
| 69 type_ = AUDIO; | 69 type_ = AUDIO; |
| 70 break; | 70 break; |
| 71 case CODEC_TYPE_VIDEO: | 71 case AVMEDIA_TYPE_VIDEO: |
| 72 type_ = VIDEO; | 72 type_ = VIDEO; |
| 73 break; | 73 break; |
| 74 default: | 74 default: |
| 75 NOTREACHED(); | 75 NOTREACHED(); |
| 76 break; | 76 break; |
| 77 } | 77 } |
| 78 | 78 |
| 79 // Calculate the duration. | 79 // Calculate the duration. |
| 80 duration_ = ConvertStreamTimestamp(stream->time_base, stream->duration); | 80 duration_ = ConvertStreamTimestamp(stream->time_base, stream->duration); |
| 81 } | 81 } |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 base::TimeDelta FFmpegDemuxer::GetStartTime() const { | 354 base::TimeDelta FFmpegDemuxer::GetStartTime() const { |
| 355 return start_time_; | 355 return start_time_; |
| 356 } | 356 } |
| 357 | 357 |
| 358 int FFmpegDemuxer::Read(int size, uint8* data) { | 358 int FFmpegDemuxer::Read(int size, uint8* data) { |
| 359 DCHECK(data_source_); | 359 DCHECK(data_source_); |
| 360 | 360 |
| 361 // If read has ever failed, return with an error. | 361 // If read has ever failed, return with an error. |
| 362 // TODO(hclam): use a more meaningful constant as error. | 362 // TODO(hclam): use a more meaningful constant as error. |
| 363 if (read_has_failed_) | 363 if (read_has_failed_) |
| 364 return AVERROR_IO; | 364 return AVERROR(EIO); |
| 365 | 365 |
| 366 // Even though FFmpeg defines AVERROR_EOF, it's not to be used with I/O | 366 // Even though FFmpeg defines AVERROR_EOF, it's not to be used with I/O |
| 367 // routines. Instead return 0 for any read at or past EOF. | 367 // routines. Instead return 0 for any read at or past EOF. |
| 368 int64 file_size; | 368 int64 file_size; |
| 369 if (data_source_->GetSize(&file_size) && read_position_ >= file_size) | 369 if (data_source_->GetSize(&file_size) && read_position_ >= file_size) |
| 370 return 0; | 370 return 0; |
| 371 | 371 |
| 372 // Asynchronous read from data source. | 372 // Asynchronous read from data source. |
| 373 data_source_->Read(read_position_, size, data, | 373 data_source_->Read(read_position_, size, data, |
| 374 NewCallback(this, &FFmpegDemuxer::OnReadCompleted)); | 374 NewCallback(this, &FFmpegDemuxer::OnReadCompleted)); |
| 375 | 375 |
| 376 // TODO(hclam): The method is called on the demuxer thread and this method | 376 // TODO(hclam): The method is called on the demuxer thread and this method |
| 377 // call will block the thread. We need to implemented an additional thread to | 377 // call will block the thread. We need to implemented an additional thread to |
| 378 // let FFmpeg demuxer methods to run on. | 378 // let FFmpeg demuxer methods to run on. |
| 379 size_t last_read_bytes = WaitForRead(); | 379 size_t last_read_bytes = WaitForRead(); |
| 380 if (last_read_bytes == DataSource::kReadError) { | 380 if (last_read_bytes == DataSource::kReadError) { |
| 381 if (host()) | 381 if (host()) |
| 382 host()->SetError(PIPELINE_ERROR_READ); | 382 host()->SetError(PIPELINE_ERROR_READ); |
| 383 else | 383 else |
| 384 deferred_status_ = PIPELINE_ERROR_READ; | 384 deferred_status_ = PIPELINE_ERROR_READ; |
| 385 | 385 |
| 386 // Returns with a negative number to signal an error to FFmpeg. | 386 // Returns with a negative number to signal an error to FFmpeg. |
| 387 read_has_failed_ = true; | 387 read_has_failed_ = true; |
| 388 return AVERROR_IO; | 388 return AVERROR(EIO); |
| 389 } | 389 } |
| 390 read_position_ += last_read_bytes; | 390 read_position_ += last_read_bytes; |
| 391 | 391 |
| 392 if (host()) | 392 if (host()) |
| 393 host()->SetCurrentReadPosition(read_position_); | 393 host()->SetCurrentReadPosition(read_position_); |
| 394 | 394 |
| 395 return last_read_bytes; | 395 return last_read_bytes; |
| 396 } | 396 } |
| 397 | 397 |
| 398 bool FFmpegDemuxer::GetPosition(int64* position_out) { | 398 bool FFmpegDemuxer::GetPosition(int64* position_out) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 return; | 464 return; |
| 465 } | 465 } |
| 466 | 466 |
| 467 // Create demuxer streams for all supported streams. | 467 // Create demuxer streams for all supported streams. |
| 468 streams_.resize(DemuxerStream::NUM_TYPES); | 468 streams_.resize(DemuxerStream::NUM_TYPES); |
| 469 base::TimeDelta max_duration; | 469 base::TimeDelta max_duration; |
| 470 const bool kDemuxerIsWebm = !strcmp("webm", format_context_->iformat->name); | 470 const bool kDemuxerIsWebm = !strcmp("webm", format_context_->iformat->name); |
| 471 bool no_supported_streams = true; | 471 bool no_supported_streams = true; |
| 472 for (size_t i = 0; i < format_context_->nb_streams; ++i) { | 472 for (size_t i = 0; i < format_context_->nb_streams; ++i) { |
| 473 AVCodecContext* codec_context = format_context_->streams[i]->codec; | 473 AVCodecContext* codec_context = format_context_->streams[i]->codec; |
| 474 CodecType codec_type = codec_context->codec_type; | 474 AVMediaType codec_type = codec_context->codec_type; |
| 475 if (codec_type == CODEC_TYPE_AUDIO || codec_type == CODEC_TYPE_VIDEO) { | 475 if (codec_type == AVMEDIA_TYPE_AUDIO || codec_type == AVMEDIA_TYPE_VIDEO) { |
| 476 AVStream* stream = format_context_->streams[i]; | 476 AVStream* stream = format_context_->streams[i]; |
| 477 // WebM is currently strictly VP8 and Vorbis. | 477 // WebM is currently strictly VP8 and Vorbis. |
| 478 if (kDemuxerIsWebm && (stream->codec->codec_id != CODEC_ID_VP8 && | 478 if (kDemuxerIsWebm && (stream->codec->codec_id != CODEC_ID_VP8 && |
| 479 stream->codec->codec_id != CODEC_ID_VORBIS)) { | 479 stream->codec->codec_id != CODEC_ID_VORBIS)) { |
| 480 packet_streams_.push_back(NULL); | 480 packet_streams_.push_back(NULL); |
| 481 continue; | 481 continue; |
| 482 } | 482 } |
| 483 | 483 |
| 484 scoped_refptr<FFmpegDemuxerStream> demuxer_stream( | 484 scoped_refptr<FFmpegDemuxerStream> demuxer_stream( |
| 485 new FFmpegDemuxerStream(this, stream)); | 485 new FFmpegDemuxerStream(this, stream)); |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 | 640 |
| 641 StreamVector::iterator iter; | 641 StreamVector::iterator iter; |
| 642 for (size_t i = 0; i < packet_streams_.size(); ++i) { | 642 for (size_t i = 0; i < packet_streams_.size(); ++i) { |
| 643 if (!packet_streams_[i]) | 643 if (!packet_streams_[i]) |
| 644 continue; | 644 continue; |
| 645 | 645 |
| 646 // If the codec type is audio, remove the reference. DemuxTask() will | 646 // If the codec type is audio, remove the reference. DemuxTask() will |
| 647 // look for such reference, and this will result in deleting the | 647 // look for such reference, and this will result in deleting the |
| 648 // audio packets after they are demuxed. | 648 // audio packets after they are demuxed. |
| 649 if (packet_streams_[i]->GetAVStream()->codec->codec_type == | 649 if (packet_streams_[i]->GetAVStream()->codec->codec_type == |
| 650 CODEC_TYPE_AUDIO) { | 650 AVMEDIA_TYPE_AUDIO) { |
| 651 packet_streams_[i] = NULL; | 651 packet_streams_[i] = NULL; |
| 652 } | 652 } |
| 653 } | 653 } |
| 654 } | 654 } |
| 655 | 655 |
| 656 bool FFmpegDemuxer::StreamsHavePendingReads() { | 656 bool FFmpegDemuxer::StreamsHavePendingReads() { |
| 657 DCHECK_EQ(MessageLoop::current(), message_loop_); | 657 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 658 StreamVector::iterator iter; | 658 StreamVector::iterator iter; |
| 659 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 659 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
| 660 if (*iter && (*iter)->HasPendingReads()) { | 660 if (*iter && (*iter)->HasPendingReads()) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 684 read_event_.Wait(); | 684 read_event_.Wait(); |
| 685 return last_read_bytes_; | 685 return last_read_bytes_; |
| 686 } | 686 } |
| 687 | 687 |
| 688 void FFmpegDemuxer::SignalReadCompleted(size_t size) { | 688 void FFmpegDemuxer::SignalReadCompleted(size_t size) { |
| 689 last_read_bytes_ = size; | 689 last_read_bytes_ = size; |
| 690 read_event_.Signal(); | 690 read_event_.Signal(); |
| 691 } | 691 } |
| 692 | 692 |
| 693 } // namespace media | 693 } // namespace media |
| OLD | NEW |