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.h" | 9 #include "base/stl_util.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 data_source_->set_host(filter_host); | 324 data_source_->set_host(filter_host); |
325 if (max_duration_.InMicroseconds() >= 0) | 325 if (max_duration_.InMicroseconds() >= 0) |
326 host()->SetDuration(max_duration_); | 326 host()->SetDuration(max_duration_); |
327 if (read_position_ > 0) | 327 if (read_position_ > 0) |
328 host()->SetCurrentReadPosition(read_position_); | 328 host()->SetCurrentReadPosition(read_position_); |
329 if (deferred_status_ != PIPELINE_OK) | 329 if (deferred_status_ != PIPELINE_OK) |
330 host()->SetError(deferred_status_); | 330 host()->SetError(deferred_status_); |
331 } | 331 } |
332 | 332 |
333 void FFmpegDemuxer::Initialize(DataSource* data_source, | 333 void FFmpegDemuxer::Initialize(DataSource* data_source, |
334 PipelineStatusCallback* callback) { | 334 const PipelineStatusCB& callback) { |
335 message_loop_->PostTask( | 335 message_loop_->PostTask( |
336 FROM_HERE, | 336 FROM_HERE, |
337 NewRunnableMethod(this, | 337 NewRunnableMethod(this, |
338 &FFmpegDemuxer::InitializeTask, | 338 &FFmpegDemuxer::InitializeTask, |
339 make_scoped_refptr(data_source), | 339 make_scoped_refptr(data_source), |
340 callback)); | 340 callback)); |
341 } | 341 } |
342 | 342 |
343 scoped_refptr<DemuxerStream> FFmpegDemuxer::GetStream( | 343 scoped_refptr<DemuxerStream> FFmpegDemuxer::GetStream( |
344 DemuxerStream::Type type) { | 344 DemuxerStream::Type type) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 DCHECK(data_source_); | 419 DCHECK(data_source_); |
420 | 420 |
421 return data_source_->IsStreaming(); | 421 return data_source_->IsStreaming(); |
422 } | 422 } |
423 | 423 |
424 MessageLoop* FFmpegDemuxer::message_loop() { | 424 MessageLoop* FFmpegDemuxer::message_loop() { |
425 return message_loop_; | 425 return message_loop_; |
426 } | 426 } |
427 | 427 |
428 void FFmpegDemuxer::InitializeTask(DataSource* data_source, | 428 void FFmpegDemuxer::InitializeTask(DataSource* data_source, |
429 PipelineStatusCallback* callback) { | 429 const PipelineStatusCB& callback) { |
430 DCHECK_EQ(MessageLoop::current(), message_loop_); | 430 DCHECK_EQ(MessageLoop::current(), message_loop_); |
431 scoped_ptr<PipelineStatusCallback> callback_deleter(callback); | |
432 | 431 |
433 data_source_ = data_source; | 432 data_source_ = data_source; |
434 if (host()) | 433 if (host()) |
435 data_source_->set_host(host()); | 434 data_source_->set_host(host()); |
436 | 435 |
437 // Add ourself to Protocol list and get our unique key. | 436 // Add ourself to Protocol list and get our unique key. |
438 std::string key = FFmpegGlue::GetInstance()->AddProtocol(this); | 437 std::string key = FFmpegGlue::GetInstance()->AddProtocol(this); |
439 | 438 |
440 // Open FFmpeg AVFormatContext. | 439 // Open FFmpeg AVFormatContext. |
441 DCHECK(!format_context_); | 440 DCHECK(!format_context_); |
442 AVFormatContext* context = NULL; | 441 AVFormatContext* context = NULL; |
443 int result = av_open_input_file(&context, key.c_str(), NULL, 0, NULL); | 442 int result = av_open_input_file(&context, key.c_str(), NULL, 0, NULL); |
444 | 443 |
445 // Remove ourself from protocol list. | 444 // Remove ourself from protocol list. |
446 FFmpegGlue::GetInstance()->RemoveProtocol(this); | 445 FFmpegGlue::GetInstance()->RemoveProtocol(this); |
447 | 446 |
448 if (result < 0) { | 447 if (result < 0) { |
449 callback->Run(DEMUXER_ERROR_COULD_NOT_OPEN); | 448 callback.Run(DEMUXER_ERROR_COULD_NOT_OPEN); |
450 return; | 449 return; |
451 } | 450 } |
452 | 451 |
453 DCHECK(context); | 452 DCHECK(context); |
454 format_context_ = context; | 453 format_context_ = context; |
455 | 454 |
456 // Fully initialize AVFormatContext by parsing the stream a little. | 455 // Fully initialize AVFormatContext by parsing the stream a little. |
457 result = av_find_stream_info(format_context_); | 456 result = av_find_stream_info(format_context_); |
458 if (result < 0) { | 457 if (result < 0) { |
459 callback->Run(DEMUXER_ERROR_COULD_NOT_PARSE); | 458 callback.Run(DEMUXER_ERROR_COULD_NOT_PARSE); |
460 return; | 459 return; |
461 } | 460 } |
462 | 461 |
463 // Create demuxer streams for all supported streams. | 462 // Create demuxer streams for all supported streams. |
464 streams_.resize(DemuxerStream::NUM_TYPES); | 463 streams_.resize(DemuxerStream::NUM_TYPES); |
465 base::TimeDelta max_duration; | 464 base::TimeDelta max_duration; |
466 const bool kDemuxerIsWebm = !strcmp("webm", format_context_->iformat->name); | 465 const bool kDemuxerIsWebm = !strcmp("webm", format_context_->iformat->name); |
467 bool no_supported_streams = true; | 466 bool no_supported_streams = true; |
468 for (size_t i = 0; i < format_context_->nb_streams; ++i) { | 467 for (size_t i = 0; i < format_context_->nb_streams; ++i) { |
469 AVCodecContext* codec_context = format_context_->streams[i]->codec; | 468 AVCodecContext* codec_context = format_context_->streams[i]->codec; |
(...skipping 20 matching lines...) Expand all Loading... |
490 if (start_time_ == kNoTimestamp || first_dts < start_time_) | 489 if (start_time_ == kNoTimestamp || first_dts < start_time_) |
491 start_time_ = first_dts; | 490 start_time_ = first_dts; |
492 } | 491 } |
493 } | 492 } |
494 packet_streams_.push_back(demuxer_stream); | 493 packet_streams_.push_back(demuxer_stream); |
495 } else { | 494 } else { |
496 packet_streams_.push_back(NULL); | 495 packet_streams_.push_back(NULL); |
497 } | 496 } |
498 } | 497 } |
499 if (no_supported_streams) { | 498 if (no_supported_streams) { |
500 callback->Run(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); | 499 callback.Run(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); |
501 return; | 500 return; |
502 } | 501 } |
503 if (format_context_->duration != static_cast<int64_t>(AV_NOPTS_VALUE)) { | 502 if (format_context_->duration != static_cast<int64_t>(AV_NOPTS_VALUE)) { |
504 // If there is a duration value in the container use that to find the | 503 // If there is a duration value in the container use that to find the |
505 // maximum between it and the duration from A/V streams. | 504 // maximum between it and the duration from A/V streams. |
506 const AVRational av_time_base = {1, AV_TIME_BASE}; | 505 const AVRational av_time_base = {1, AV_TIME_BASE}; |
507 max_duration = | 506 max_duration = |
508 std::max(max_duration, | 507 std::max(max_duration, |
509 ConvertFromTimeBase(av_time_base, format_context_->duration)); | 508 ConvertFromTimeBase(av_time_base, format_context_->duration)); |
510 } else { | 509 } else { |
511 // If the duration is not a valid value. Assume that this is a live stream | 510 // If the duration is not a valid value. Assume that this is a live stream |
512 // and we set duration to the maximum int64 number to represent infinity. | 511 // and we set duration to the maximum int64 number to represent infinity. |
513 max_duration = base::TimeDelta::FromMicroseconds( | 512 max_duration = base::TimeDelta::FromMicroseconds( |
514 Limits::kMaxTimeInMicroseconds); | 513 Limits::kMaxTimeInMicroseconds); |
515 } | 514 } |
516 | 515 |
517 // Some demuxers, like WAV, do not put timestamps on their frames. We | 516 // Some demuxers, like WAV, do not put timestamps on their frames. We |
518 // assume the the start time is 0. | 517 // assume the the start time is 0. |
519 if (start_time_ == kNoTimestamp) | 518 if (start_time_ == kNoTimestamp) |
520 start_time_ = base::TimeDelta(); | 519 start_time_ = base::TimeDelta(); |
521 | 520 |
522 // Good to go: set the duration and notify we're done initializing. | 521 // Good to go: set the duration and notify we're done initializing. |
523 if (host()) | 522 if (host()) |
524 host()->SetDuration(max_duration); | 523 host()->SetDuration(max_duration); |
525 max_duration_ = max_duration; | 524 max_duration_ = max_duration; |
526 callback->Run(PIPELINE_OK); | 525 callback.Run(PIPELINE_OK); |
527 } | 526 } |
528 | 527 |
529 void FFmpegDemuxer::SeekTask(base::TimeDelta time, const FilterStatusCB& cb) { | 528 void FFmpegDemuxer::SeekTask(base::TimeDelta time, const FilterStatusCB& cb) { |
530 DCHECK_EQ(MessageLoop::current(), message_loop_); | 529 DCHECK_EQ(MessageLoop::current(), message_loop_); |
531 | 530 |
532 // TODO(scherkus): remove this by separating Seek() from Flush() from | 531 // TODO(scherkus): remove this by separating Seek() from Flush() from |
533 // Preroll() states (i.e., the implicit Seek(0) should really be a Preroll()). | 532 // Preroll() states (i.e., the implicit Seek(0) should really be a Preroll()). |
534 if (first_seek_hack_) { | 533 if (first_seek_hack_) { |
535 first_seek_hack_ = false; | 534 first_seek_hack_ = false; |
536 | 535 |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
680 read_event_.Wait(); | 679 read_event_.Wait(); |
681 return last_read_bytes_; | 680 return last_read_bytes_; |
682 } | 681 } |
683 | 682 |
684 void FFmpegDemuxer::SignalReadCompleted(size_t size) { | 683 void FFmpegDemuxer::SignalReadCompleted(size_t size) { |
685 last_read_bytes_ = size; | 684 last_read_bytes_ = size; |
686 read_event_.Signal(); | 685 read_event_.Signal(); |
687 } | 686 } |
688 | 687 |
689 } // namespace media | 688 } // namespace media |
OLD | NEW |