Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(920)

Unified Diff: media/base/android/media_codec_decoder.cc

Issue 1194423008: Revert of Audio and video decoders for MediaCodecPlayer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/base/android/media_codec_decoder.h ('k') | media/base/android/media_codec_decoder_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/android/media_codec_decoder.cc
diff --git a/media/base/android/media_codec_decoder.cc b/media/base/android/media_codec_decoder.cc
deleted file mode 100644
index 21211adaec00ec3236b25c91b86c5e8ec0813102..0000000000000000000000000000000000000000
--- a/media/base/android/media_codec_decoder.cc
+++ /dev/null
@@ -1,598 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/base/android/media_codec_decoder.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback_helpers.h"
-#include "base/logging.h"
-#include "media/base/android/media_codec_bridge.h"
-
-namespace media {
-
-namespace {
-
-// Stop requesting new data in the kPrefetching state when the queue size
-// reaches this limit.
-const int kPrefetchLimit = 8;
-
-// Request new data in the kRunning state if the queue size is less than this.
-const int kPlaybackLowLimit = 4;
-
-// Posting delay of the next frame processing, in milliseconds
-const int kNextFrameDelay = 1;
-
-// Timeout for dequeuing an input buffer from MediaCodec in milliseconds.
-const int kInputBufferTimeout = 20;
-
-// Timeout for dequeuing an output buffer from MediaCodec in milliseconds.
-const int kOutputBufferTimeout = 20;
-}
-
-MediaCodecDecoder::MediaCodecDecoder(
- const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
- const base::Closure& request_data_cb,
- const base::Closure& starvation_cb,
- const base::Closure& stop_done_cb,
- const base::Closure& error_cb,
- const char* decoder_thread_name)
- : media_task_runner_(media_task_runner),
- decoder_thread_(decoder_thread_name),
- request_data_cb_(request_data_cb),
- starvation_cb_(starvation_cb),
- stop_done_cb_(stop_done_cb),
- error_cb_(error_cb),
- state_(kStopped),
- eos_enqueued_(false),
- completed_(false),
- last_frame_posted_(false),
- weak_factory_(this) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- DVLOG(1) << "Decoder::Decoder() " << decoder_thread_name;
-
- internal_error_cb_ =
- base::Bind(&MediaCodecDecoder::OnCodecError, weak_factory_.GetWeakPtr());
-}
-
-MediaCodecDecoder::~MediaCodecDecoder() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- DVLOG(1) << "Decoder::~Decoder()";
-
- // NB: ReleaseDecoderResources() is virtual
- ReleaseDecoderResources();
-}
-
-const char* MediaCodecDecoder::class_name() const {
- return "Decoder";
-}
-
-void MediaCodecDecoder::ReleaseDecoderResources() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- DVLOG(1) << class_name() << "::" << __FUNCTION__;
-
- decoder_thread_.Stop(); // synchronous
- state_ = kStopped;
- media_codec_bridge_.reset();
-}
-
-void MediaCodecDecoder::Flush() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- DVLOG(1) << class_name() << "::" << __FUNCTION__;
-
- DCHECK_EQ(GetState(), kStopped);
-
- eos_enqueued_ = false;
- completed_ = false;
- au_queue_.Flush();
-
- if (media_codec_bridge_) {
- // MediaCodecBridge::Reset() performs MediaCodecBridge.flush()
- MediaCodecStatus flush_status = media_codec_bridge_->Reset();
- if (flush_status != MEDIA_CODEC_OK) {
- DVLOG(0) << class_name() << "::" << __FUNCTION__
- << "MediaCodecBridge::Reset() failed";
- media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
- }
- }
-}
-
-void MediaCodecDecoder::ReleaseMediaCodec() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- DVLOG(1) << class_name() << "::" << __FUNCTION__;
-
- media_codec_bridge_.reset();
-}
-
-bool MediaCodecDecoder::IsPrefetchingOrPlaying() const {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- base::AutoLock lock(state_lock_);
- return state_ == kPrefetching || state_ == kRunning;
-}
-
-bool MediaCodecDecoder::IsStopped() const {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- return GetState() == kStopped;
-}
-
-bool MediaCodecDecoder::IsCompleted() const {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- return completed_;
-}
-
-base::android::ScopedJavaLocalRef<jobject> MediaCodecDecoder::GetMediaCrypto() {
- base::android::ScopedJavaLocalRef<jobject> media_crypto;
-
- // TODO(timav): implement DRM.
- // drm_bridge_ is not implemented
- // if (drm_bridge_)
- // media_crypto = drm_bridge_->GetMediaCrypto();
- return media_crypto;
-}
-
-void MediaCodecDecoder::Prefetch(const base::Closure& prefetch_done_cb) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- DVLOG(1) << class_name() << "::" << __FUNCTION__;
-
- DCHECK(GetState() == kStopped);
-
- prefetch_done_cb_ = prefetch_done_cb;
-
- SetState(kPrefetching);
- PrefetchNextChunk();
-}
-
-MediaCodecDecoder::ConfigStatus MediaCodecDecoder::Configure() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- DVLOG(1) << class_name() << "::" << __FUNCTION__;
-
- if (GetState() == kError) {
- DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError";
- return CONFIG_FAILURE;
- }
-
- // Here I assume that OnDemuxerConfigsAvailable won't come
- // in the middle of demuxer data.
-
- if (media_codec_bridge_) {
- DVLOG(1) << class_name() << "::" << __FUNCTION__
- << ": reconfiguration is not required, ignoring";
- return CONFIG_OK;
- }
-
- return ConfigureInternal();
-}
-
-bool MediaCodecDecoder::Start(base::TimeDelta current_time) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- DVLOG(1) << class_name() << "::" << __FUNCTION__
- << " current_time:" << current_time;
-
- DecoderState state = GetState();
- if (state == kRunning) {
- DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": already started";
- return true; // already started
- }
-
- if (state != kPrefetched) {
- DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state "
- << AsString(state) << " ignoring";
- return false;
- }
-
- if (!media_codec_bridge_) {
- DVLOG(0) << class_name() << "::" << __FUNCTION__
- << ": not configured, ignoring";
- return false;
- }
-
- DCHECK(!decoder_thread_.IsRunning());
-
- // We only synchronize video stream.
- // When audio is present, the |current_time| is audio time.
- SynchronizePTSWithTime(current_time);
-
- last_frame_posted_ = false;
-
- // Start the decoder thread
- if (!decoder_thread_.Start()) {
- DVLOG(1) << class_name() << "::" << __FUNCTION__
- << ": cannot start decoder thread";
- return false;
- }
-
- SetState(kRunning);
-
- decoder_thread_.task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)));
-
- return true;
-}
-
-void MediaCodecDecoder::SyncStop() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- DVLOG(1) << class_name() << "::" << __FUNCTION__;
-
- if (GetState() == kError) {
- DVLOG(0) << class_name() << "::" << __FUNCTION__
- << ": wrong state kError, ignoring";
- return;
- }
-
- // After this method returns, decoder thread will not be running.
-
- decoder_thread_.Stop(); // synchronous
- state_ = kStopped;
-
- // Shall we move |delayed_buffers_| from VideoDecoder to Decoder class?
- ReleaseDelayedBuffers();
-}
-
-void MediaCodecDecoder::RequestToStop() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- DVLOG(1) << class_name() << "::" << __FUNCTION__;
-
- DecoderState state = GetState();
- switch (state) {
- case kError:
- DVLOG(0) << class_name() << "::" << __FUNCTION__
- << ": wrong state kError, ignoring";
- break;
- case kRunning:
- SetState(kStopping);
- break;
- case kStopping:
- break; // ignore
- case kStopped:
- case kPrefetching:
- case kPrefetched:
- // There is nothing to wait for, we can sent nofigication right away.
- DCHECK(!decoder_thread_.IsRunning());
- SetState(kStopped);
- media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
- break;
- default:
- NOTREACHED();
- break;
- }
-}
-
-void MediaCodecDecoder::OnLastFrameRendered(bool completed) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- DVLOG(1) << class_name() << "::" << __FUNCTION__
- << " completed:" << completed;
-
- decoder_thread_.Stop(); // synchronous
- state_ = kStopped;
- completed_ = completed;
-
- media_task_runner_->PostTask(FROM_HERE, stop_done_cb_);
-}
-
-void MediaCodecDecoder::OnDemuxerDataAvailable(const DemuxerData& data) {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- DVLOG(2) << class_name() << "::" << __FUNCTION__
- << " #AUs:" << data.access_units.size()
- << " #Configs:" << data.demuxer_configs.size();
-#if !defined(NDEBUG)
- for (const auto& unit : data.access_units)
- DVLOG(2) << class_name() << "::" << __FUNCTION__ << " au: " << unit;
-#endif
-
- au_queue_.PushBack(data);
-
- if (state_ == kPrefetching)
- PrefetchNextChunk();
-}
-
-int MediaCodecDecoder::NumDelayedRenderTasks() const {
- return 0;
-}
-
-void MediaCodecDecoder::CheckLastFrame(bool eos_encountered,
- bool has_delayed_tasks) {
- DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
-
- bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks;
-
- if (last_frame_when_stopping || eos_encountered) {
- media_task_runner_->PostTask(
- FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered,
- weak_factory_.GetWeakPtr(), eos_encountered));
- last_frame_posted_ = true;
- }
-}
-
-void MediaCodecDecoder::OnCodecError() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- SetState(kError);
- error_cb_.Run();
-}
-
-void MediaCodecDecoder::PrefetchNextChunk() {
- DCHECK(media_task_runner_->BelongsToCurrentThread());
-
- DVLOG(1) << class_name() << "::" << __FUNCTION__;
-
- AccessUnitQueue::Info au_info = au_queue_.GetInfo();
-
- if (eos_enqueued_ || au_info.length >= kPrefetchLimit || au_info.has_eos) {
- // We are done prefetching
- SetState(kPrefetched);
- DVLOG(1) << class_name() << "::" << __FUNCTION__ << " posting PrefetchDone";
- media_task_runner_->PostTask(FROM_HERE,
- base::ResetAndReturn(&prefetch_done_cb_));
- return;
- }
-
- request_data_cb_.Run();
-}
-
-void MediaCodecDecoder::ProcessNextFrame() {
- DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
-
- DVLOG(2) << class_name() << "::" << __FUNCTION__;
-
- DecoderState state = GetState();
-
- if (state != kRunning && state != kStopping) {
- DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": not running";
- return;
- }
-
- if (state == kStopping) {
- if (NumDelayedRenderTasks() == 0 && !last_frame_posted_) {
- DVLOG(1) << class_name() << "::" << __FUNCTION__
- << ": kStopping, posting OnLastFrameRendered";
- media_task_runner_->PostTask(
- FROM_HERE, base::Bind(&MediaCodecDecoder::OnLastFrameRendered,
- weak_factory_.GetWeakPtr(), false));
- last_frame_posted_ = true;
- }
-
- // We can stop processing, the |au_queue_| and MediaCodec queues can freeze.
- // We only need to let finish the delayed rendering tasks.
- return;
- }
-
- DCHECK(state == kRunning);
-
- if (!EnqueueInputBuffer())
- return;
-
- bool eos_encountered = false;
- if (!DepleteOutputBufferQueue(&eos_encountered))
- return;
-
- if (eos_encountered) {
- DVLOG(1) << class_name() << "::" << __FUNCTION__
- << " EOS dequeued, stopping frame processing";
- return;
- }
-
- // We need a small delay if we want to stop this thread by
- // decoder_thread_.Stop() reliably.
- // The decoder thread message loop processes all pending
- // (but not delayed) tasks before it can quit; without a delay
- // the message loop might be forever processing the pendng tasks.
- decoder_thread_.task_runner()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&MediaCodecDecoder::ProcessNextFrame, base::Unretained(this)),
- base::TimeDelta::FromMilliseconds(kNextFrameDelay));
-}
-
-// Returns false if we should stop decoding process. Right now
-// it happens if we got MediaCodec error or detected starvation.
-bool MediaCodecDecoder::EnqueueInputBuffer() {
- DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
-
- DVLOG(2) << class_name() << "::" << __FUNCTION__;
-
- if (eos_enqueued_) {
- DVLOG(1) << class_name() << "::" << __FUNCTION__
- << ": eos_enqueued, returning";
- return true; // Nothing to do
- }
-
- // Keep the number pending video frames low, ideally maintaining
- // the same audio and video duration after stop request
- if (NumDelayedRenderTasks() > 1) {
- DVLOG(2) << class_name() << "::" << __FUNCTION__ << ": # delayed buffers ("
- << NumDelayedRenderTasks() << ") exceeds 1, returning";
- return true; // Nothing to do
- }
-
- // Get the next frame from the queue and the queue info
-
- AccessUnitQueue::Info au_info = au_queue_.GetInfo();
-
- // Request the data from Demuxer
- if (au_info.length <= kPlaybackLowLimit && !au_info.has_eos)
- media_task_runner_->PostTask(FROM_HERE, request_data_cb_);
-
- // Get the next frame from the queue
-
- if (!au_info.length) {
- // Report starvation and return, Start() will be called again later.
- DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": starvation detected";
- media_task_runner_->PostTask(FROM_HERE, starvation_cb_);
- return false;
- }
-
- if (au_info.configs) {
- DVLOG(1) << class_name() << "::" << __FUNCTION__
- << ": received new configs, not implemented";
- // post an error for now?
- media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
- return false;
- }
-
- // Dequeue input buffer
-
- base::TimeDelta timeout =
- base::TimeDelta::FromMilliseconds(kInputBufferTimeout);
- int index = -1;
- MediaCodecStatus status =
- media_codec_bridge_->DequeueInputBuffer(timeout, &index);
-
- DVLOG(2) << class_name() << ":: DequeueInputBuffer index:" << index;
-
- switch (status) {
- case MEDIA_CODEC_ERROR:
- DVLOG(0) << class_name() << "::" << __FUNCTION__
- << ": MEDIA_CODEC_ERROR DequeueInputBuffer failed";
- media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
- return false;
-
- case MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER:
- return true;
-
- default:
- break;
- }
-
- // We got the buffer
- DCHECK_EQ(status, MEDIA_CODEC_OK);
- DCHECK_GE(index, 0);
-
- const AccessUnit* unit = au_info.front_unit;
- DCHECK(unit);
-
- if (unit->is_end_of_stream) {
- DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": QueueEOS";
- media_codec_bridge_->QueueEOS(index);
- eos_enqueued_ = true;
- return true;
- }
-
- DVLOG(2) << class_name() << ":: QueueInputBuffer pts:" << unit->timestamp;
-
- status = media_codec_bridge_->QueueInputBuffer(
- index, &unit->data[0], unit->data.size(), unit->timestamp);
-
- if (status == MEDIA_CODEC_ERROR) {
- DVLOG(0) << class_name() << "::" << __FUNCTION__
- << ": MEDIA_CODEC_ERROR: QueueInputBuffer failed";
- media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
- return false;
- }
-
- // Have successfully queued input buffer, go to next access unit.
- au_queue_.Advance();
- return true;
-}
-
-// Returns false if there was MediaCodec error.
-bool MediaCodecDecoder::DepleteOutputBufferQueue(bool* eos_encountered) {
- DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
-
- DVLOG(2) << class_name() << "::" << __FUNCTION__;
-
- int buffer_index = 0;
- size_t offset = 0;
- size_t size = 0;
- base::TimeDelta pts;
- MediaCodecStatus status;
-
- base::TimeDelta timeout =
- base::TimeDelta::FromMilliseconds(kOutputBufferTimeout);
-
- // Extract all output buffers that are available.
- // Usually there will be only one, but sometimes it is preceeded by
- // MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED or MEDIA_CODEC_OUTPUT_FORMAT_CHANGED.
- do {
- status = media_codec_bridge_->DequeueOutputBuffer(
- timeout, &buffer_index, &offset, &size, &pts, eos_encountered, nullptr);
-
- // Reset the timeout to 0 for the subsequent DequeueOutputBuffer() calls
- // to quickly break the loop after we got all currently available buffers.
- timeout = base::TimeDelta::FromMilliseconds(0);
-
- switch (status) {
- case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
- // Output buffers are replaced in MediaCodecBridge, nothing to do.
- break;
-
- case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
- DVLOG(2) << class_name() << "::" << __FUNCTION__
- << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED";
- OnOutputFormatChanged();
- break;
-
- case MEDIA_CODEC_OK:
- // We got the decoded frame
- Render(buffer_index, size, true, pts, *eos_encountered);
- break;
-
- case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
- // Nothing to do.
- break;
-
- case MEDIA_CODEC_ERROR:
- DVLOG(0) << class_name() << "::" << __FUNCTION__
- << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer";
- media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
- break;
-
- default:
- NOTREACHED();
- break;
- }
-
- } while (status != MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER &&
- status != MEDIA_CODEC_ERROR && !*eos_encountered);
-
- return status != MEDIA_CODEC_ERROR;
-}
-
-MediaCodecDecoder::DecoderState MediaCodecDecoder::GetState() const {
- base::AutoLock lock(state_lock_);
- return state_;
-}
-
-void MediaCodecDecoder::SetState(DecoderState state) {
- DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << state;
-
- base::AutoLock lock(state_lock_);
- state_ = state;
-}
-
-#undef RETURN_STRING
-#define RETURN_STRING(x) \
- case x: \
- return #x;
-
-const char* MediaCodecDecoder::AsString(DecoderState state) {
- switch (state) {
- RETURN_STRING(kStopped);
- RETURN_STRING(kPrefetching);
- RETURN_STRING(kPrefetched);
- RETURN_STRING(kRunning);
- RETURN_STRING(kStopping);
- RETURN_STRING(kError);
- default:
- return "Unknown DecoderState";
- }
-}
-
-#undef RETURN_STRING
-
-} // namespace media
« no previous file with comments | « media/base/android/media_codec_decoder.h ('k') | media/base/android/media_codec_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698