12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/filters/blocking_url_protocol.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/data_source.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/ffmpeg/ffmpeg_common.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace media {
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BlockingUrlProtocol::BlockingUrlProtocol(
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DataSource* data_source,
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& error_cb)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : data_source_(data_source),
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_cb_(error_cb),
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      aborted_(true, false),  // We never want to reset |aborted_|.
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      read_complete_(false, false),
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      last_read_bytes_(0),
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      read_position_(0) {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BlockingUrlProtocol::~BlockingUrlProtocol() {}
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BlockingUrlProtocol::Abort() {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aborted_.Signal();
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int BlockingUrlProtocol::Read(int size, uint8* data) {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Read errors are unrecoverable.
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (aborted_.IsSignaled())
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return AVERROR(EIO);
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Even though FFmpeg defines AVERROR_EOF, it's not to be used with I/O
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // routines. Instead return 0 for any read at or past EOF.
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 file_size;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (data_source_->GetSize(&file_size) && read_position_ >= file_size)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Blocking read from data source until either:
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   1) |last_read_bytes_| is set and |read_complete_| is signalled
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   2) |aborted_| is signalled
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data_source_->Read(read_position_, size, data, base::Bind(
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &BlockingUrlProtocol::SignalReadCompleted, base::Unretained(this)));
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::WaitableEvent* events[] = { &aborted_, &read_complete_ };
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t index = base::WaitableEvent::WaitMany(events, arraysize(events));
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (events[index] == &aborted_)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return AVERROR(EIO);
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (last_read_bytes_ == DataSource::kReadError) {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    aborted_.Signal();
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    error_cb_.Run();
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return AVERROR(EIO);
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_position_ += last_read_bytes_;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return last_read_bytes_;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BlockingUrlProtocol::GetPosition(int64* position_out) {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *position_out = read_position_;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BlockingUrlProtocol::SetPosition(int64 position) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 file_size;
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if ((data_source_->GetSize(&file_size) && position > file_size) ||
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      position < 0) {
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_position_ = position;
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BlockingUrlProtocol::GetSize(int64* size_out) {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return data_source_->GetSize(size_out);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BlockingUrlProtocol::IsStreaming() {
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return data_source_->IsStreaming();
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BlockingUrlProtocol::SignalReadCompleted(int size) {
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  last_read_bytes_ = size;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_complete_.Signal();
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace media
93