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 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
372 base::TimeDelta FFmpegDemuxer::GetStartTime() const { | 372 base::TimeDelta FFmpegDemuxer::GetStartTime() const { |
373 return start_time_; | 373 return start_time_; |
374 } | 374 } |
375 | 375 |
376 int FFmpegDemuxer::Read(int size, uint8* data) { | 376 int FFmpegDemuxer::Read(int size, uint8* data) { |
377 DCHECK(data_source_); | 377 DCHECK(data_source_); |
378 | 378 |
379 // If read has ever failed, return with an error. | 379 // If read has ever failed, return with an error. |
380 // TODO(hclam): use a more meaningful constant as error. | 380 // TODO(hclam): use a more meaningful constant as error. |
381 if (read_has_failed_) | 381 if (read_has_failed_) |
382 return AVERROR_IO; | 382 return AVERROR(EIO); |
383 | 383 |
384 // Even though FFmpeg defines AVERROR_EOF, it's not to be used with I/O | 384 // Even though FFmpeg defines AVERROR_EOF, it's not to be used with I/O |
385 // routines. Instead return 0 for any read at or past EOF. | 385 // routines. Instead return 0 for any read at or past EOF. |
386 int64 file_size; | 386 int64 file_size; |
387 if (data_source_->GetSize(&file_size) && read_position_ >= file_size) | 387 if (data_source_->GetSize(&file_size) && read_position_ >= file_size) |
388 return 0; | 388 return 0; |
389 | 389 |
390 // Asynchronous read from data source. | 390 // Asynchronous read from data source. |
391 data_source_->Read(read_position_, size, data, | 391 data_source_->Read(read_position_, size, data, |
392 NewCallback(this, &FFmpegDemuxer::OnReadCompleted)); | 392 NewCallback(this, &FFmpegDemuxer::OnReadCompleted)); |
393 | 393 |
394 // TODO(hclam): The method is called on the demuxer thread and this method | 394 // TODO(hclam): The method is called on the demuxer thread and this method |
395 // call will block the thread. We need to implemented an additional thread to | 395 // call will block the thread. We need to implemented an additional thread to |
396 // let FFmpeg demuxer methods to run on. | 396 // let FFmpeg demuxer methods to run on. |
397 size_t last_read_bytes = WaitForRead(); | 397 size_t last_read_bytes = WaitForRead(); |
398 if (last_read_bytes == DataSource::kReadError) { | 398 if (last_read_bytes == DataSource::kReadError) { |
399 if (host()) | 399 if (host()) |
400 host()->SetError(PIPELINE_ERROR_READ); | 400 host()->SetError(PIPELINE_ERROR_READ); |
401 else | 401 else |
402 deferred_status_ = PIPELINE_ERROR_READ; | 402 deferred_status_ = PIPELINE_ERROR_READ; |
403 | 403 |
404 // Returns with a negative number to signal an error to FFmpeg. | 404 // Returns with a negative number to signal an error to FFmpeg. |
405 read_has_failed_ = true; | 405 read_has_failed_ = true; |
406 return AVERROR_IO; | 406 return AVERROR(EIO); |
407 } | 407 } |
408 read_position_ += last_read_bytes; | 408 read_position_ += last_read_bytes; |
409 | 409 |
410 if (host()) | 410 if (host()) |
411 host()->SetCurrentReadPosition(read_position_); | 411 host()->SetCurrentReadPosition(read_position_); |
412 | 412 |
413 return last_read_bytes; | 413 return last_read_bytes; |
414 } | 414 } |
415 | 415 |
416 bool FFmpegDemuxer::GetPosition(int64* position_out) { | 416 bool FFmpegDemuxer::GetPosition(int64* position_out) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
456 if (host()) | 456 if (host()) |
457 data_source_->set_host(host()); | 457 data_source_->set_host(host()); |
458 | 458 |
459 // Add ourself to Protocol list and get our unique key. | 459 // Add ourself to Protocol list and get our unique key. |
460 std::string key = FFmpegGlue::GetInstance()->AddProtocol(this); | 460 std::string key = FFmpegGlue::GetInstance()->AddProtocol(this); |
461 | 461 |
462 // Open FFmpeg AVFormatContext. | 462 // Open FFmpeg AVFormatContext. |
463 DCHECK(!format_context_); | 463 DCHECK(!format_context_); |
464 AVFormatContext* context = NULL; | 464 AVFormatContext* context = NULL; |
465 int result = av_open_input_file(&context, key.c_str(), NULL, 0, NULL); | 465 int result = av_open_input_file(&context, key.c_str(), NULL, 0, NULL); |
466 | |
467 // Remove ourself from protocol list. | 466 // Remove ourself from protocol list. |
scherkus (not reviewing)
2011/06/29 17:00:36
could you add back this blank line?
ilja
2011/06/29 21:40:05
Done.
| |
468 FFmpegGlue::GetInstance()->RemoveProtocol(this); | 467 FFmpegGlue::GetInstance()->RemoveProtocol(this); |
469 | 468 |
470 if (result < 0) { | 469 if (result < 0) { |
471 callback->Run(DEMUXER_ERROR_COULD_NOT_OPEN); | 470 callback->Run(DEMUXER_ERROR_COULD_NOT_OPEN); |
472 return; | 471 return; |
473 } | 472 } |
474 | 473 |
475 DCHECK(context); | 474 DCHECK(context); |
476 format_context_ = context; | 475 format_context_ = context; |
477 | 476 |
478 // Fully initialize AVFormatContext by parsing the stream a little. | 477 // Fully initialize AVFormatContext by parsing the stream a little. |
479 result = av_find_stream_info(format_context_); | 478 result = av_find_stream_info(format_context_); |
480 if (result < 0) { | 479 if (result < 0) { |
481 callback->Run(DEMUXER_ERROR_COULD_NOT_PARSE); | 480 callback->Run(DEMUXER_ERROR_COULD_NOT_PARSE); |
482 return; | 481 return; |
483 } | 482 } |
484 | 483 |
485 // Create demuxer streams for all supported streams. | 484 // Create demuxer streams for all supported streams. |
486 streams_.resize(DemuxerStream::NUM_TYPES); | 485 streams_.resize(DemuxerStream::NUM_TYPES); |
487 base::TimeDelta max_duration; | 486 base::TimeDelta max_duration; |
488 const bool kDemuxerIsWebm = !strcmp("webm", format_context_->iformat->name); | 487 const bool kDemuxerIsWebm = !strcmp("webm", format_context_->iformat->name); |
489 bool no_supported_streams = true; | 488 bool no_supported_streams = true; |
490 for (size_t i = 0; i < format_context_->nb_streams; ++i) { | 489 for (size_t i = 0; i < format_context_->nb_streams; ++i) { |
491 AVCodecContext* codec_context = format_context_->streams[i]->codec; | 490 AVCodecContext* codec_context = format_context_->streams[i]->codec; |
492 CodecType codec_type = codec_context->codec_type; | 491 AVMediaType codec_type = codec_context->codec_type; |
493 if (codec_type == CODEC_TYPE_AUDIO || codec_type == CODEC_TYPE_VIDEO) { | 492 if (codec_type == AVMEDIA_TYPE_AUDIO || codec_type == AVMEDIA_TYPE_VIDEO) { |
494 AVStream* stream = format_context_->streams[i]; | 493 AVStream* stream = format_context_->streams[i]; |
495 // WebM is currently strictly VP8 and Vorbis. | 494 // WebM is currently strictly VP8 and Vorbis. |
496 if (kDemuxerIsWebm && (stream->codec->codec_id != CODEC_ID_VP8 && | 495 if (kDemuxerIsWebm && (stream->codec->codec_id != CODEC_ID_VP8 && |
497 stream->codec->codec_id != CODEC_ID_VORBIS)) { | 496 stream->codec->codec_id != CODEC_ID_VORBIS)) { |
498 packet_streams_.push_back(NULL); | 497 packet_streams_.push_back(NULL); |
499 continue; | 498 continue; |
500 } | 499 } |
501 | 500 |
502 scoped_refptr<FFmpegDemuxerStream> demuxer_stream( | 501 scoped_refptr<FFmpegDemuxerStream> demuxer_stream( |
503 new FFmpegDemuxerStream(this, stream)); | 502 new FFmpegDemuxerStream(this, stream)); |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
658 | 657 |
659 StreamVector::iterator iter; | 658 StreamVector::iterator iter; |
660 for (size_t i = 0; i < packet_streams_.size(); ++i) { | 659 for (size_t i = 0; i < packet_streams_.size(); ++i) { |
661 if (!packet_streams_[i]) | 660 if (!packet_streams_[i]) |
662 continue; | 661 continue; |
663 | 662 |
664 // If the codec type is audio, remove the reference. DemuxTask() will | 663 // If the codec type is audio, remove the reference. DemuxTask() will |
665 // look for such reference, and this will result in deleting the | 664 // look for such reference, and this will result in deleting the |
666 // audio packets after they are demuxed. | 665 // audio packets after they are demuxed. |
667 if (packet_streams_[i]->GetAVStream()->codec->codec_type == | 666 if (packet_streams_[i]->GetAVStream()->codec->codec_type == |
668 CODEC_TYPE_AUDIO) { | 667 AVMEDIA_TYPE_AUDIO) { |
669 packet_streams_[i] = NULL; | 668 packet_streams_[i] = NULL; |
670 } | 669 } |
671 } | 670 } |
672 } | 671 } |
673 | 672 |
674 bool FFmpegDemuxer::StreamsHavePendingReads() { | 673 bool FFmpegDemuxer::StreamsHavePendingReads() { |
675 DCHECK_EQ(MessageLoop::current(), message_loop_); | 674 DCHECK_EQ(MessageLoop::current(), message_loop_); |
676 StreamVector::iterator iter; | 675 StreamVector::iterator iter; |
677 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 676 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
678 if (*iter && (*iter)->HasPendingReads()) { | 677 if (*iter && (*iter)->HasPendingReads()) { |
(...skipping 23 matching lines...) Expand all Loading... | |
702 read_event_.Wait(); | 701 read_event_.Wait(); |
703 return last_read_bytes_; | 702 return last_read_bytes_; |
704 } | 703 } |
705 | 704 |
706 void FFmpegDemuxer::SignalReadCompleted(size_t size) { | 705 void FFmpegDemuxer::SignalReadCompleted(size_t size) { |
707 last_read_bytes_ = size; | 706 last_read_bytes_ = size; |
708 read_event_.Signal(); | 707 read_event_.Signal(); |
709 } | 708 } |
710 | 709 |
711 } // namespace media | 710 } // namespace media |
OLD | NEW |