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

Unified Diff: webrtc/sdk/android/src/jni/androidmediadecoder_jni.cc

Issue 2777203003: Android: Remove codec thread from MediaCodecVideoDecoder. (Closed)
Patch Set: Rebase. Created 3 years, 9 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 | « webrtc/sdk/android/api/org/webrtc/MediaCodecVideoDecoder.java ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/sdk/android/src/jni/androidmediadecoder_jni.cc
diff --git a/webrtc/sdk/android/src/jni/androidmediadecoder_jni.cc b/webrtc/sdk/android/src/jni/androidmediadecoder_jni.cc
index 6bd749a3bccdf22b281904f66664c9222e6be818..bcca86a917352ef09575088aa31800f5ae2623b2 100644
--- a/webrtc/sdk/android/src/jni/androidmediadecoder_jni.cc
+++ b/webrtc/sdk/android/src/jni/androidmediadecoder_jni.cc
@@ -24,7 +24,7 @@
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ref_ptr.h"
-#include "webrtc/base/thread.h"
+#include "webrtc/base/thread_checker.h"
#include "webrtc/base/timeutils.h"
#include "webrtc/common_video/h264/h264_bitstream_parser.h"
#include "webrtc/common_video/include/i420_buffer_pool.h"
@@ -65,6 +65,8 @@ using webrtc::kVideoCodecVP9;
namespace webrtc_jni {
+// All calls should be made on the decoding thread expect for release which can
+// be called after the decoder thread has been stopped.
class MediaCodecVideoDecoder : public webrtc::VideoDecoder {
public:
explicit MediaCodecVideoDecoder(
@@ -92,39 +94,12 @@ class MediaCodecVideoDecoder : public webrtc::VideoDecoder {
const char* ImplementationName() const override;
private:
- struct DecodedFrame {
- DecodedFrame(VideoFrame frame,
- int decode_time_ms,
- int64_t timestamp,
- int64_t ntp_timestamp,
- rtc::Optional<uint8_t> qp)
- : frame(std::move(frame)),
- decode_time_ms(decode_time_ms),
- qp(std::move(qp)) {
- frame.set_timestamp(timestamp);
- frame.set_ntp_time_ms(ntp_timestamp);
- }
-
- VideoFrame frame;
- int decode_time_ms;
- rtc::Optional<uint8_t> qp;
- };
-
- // Returns true if running on |codec_thread_|. Used for DCHECKing.
- bool IsOnCodecThread();
-
- int32_t InitDecodeOnCodecThread();
- int32_t ResetDecodeOnCodecThread();
- int32_t ReleaseOnCodecThread();
- int32_t DecodeOnCodecThread(const EncodedImage& inputImage,
- std::vector<DecodedFrame>* frames);
- void PollDecodedFramesOnCodecThread(std::vector<DecodedFrame>* frames);
+ int32_t InitDecodeInternal();
+ int32_t ResetDecode();
// Deliver any outputs pending in the MediaCodec to our |callback_| and return
// true on success.
- bool DeliverPendingOutputs(JNIEnv* jni,
- int dequeue_timeout_us,
- std::vector<DecodedFrame>* frames);
- int32_t ProcessHWErrorOnCodecThread();
+ bool DeliverPendingOutputs(JNIEnv* jni, int dequeue_timeout_us);
+ int32_t ProcessHWError();
void EnableFrameLogOnWarning();
void ResetVariables();
@@ -158,8 +133,7 @@ class MediaCodecVideoDecoder : public webrtc::VideoDecoder {
// State that is constant for the lifetime of this object once the ctor
// returns.
- std::unique_ptr<Thread>
- codec_thread_; // Thread on which to operate MediaCodec.
+ rtc::ThreadChecker decode_thread_checker_;
ScopedGlobalRef<jclass> j_media_codec_video_decoder_class_;
ScopedGlobalRef<jobject> j_media_codec_video_decoder_;
jmethodID j_init_decode_method_;
@@ -197,9 +171,6 @@ class MediaCodecVideoDecoder : public webrtc::VideoDecoder {
// Global references; must be deleted in Release().
std::vector<jobject> input_buffers_;
-
- // Added to on the codec thread, frames are delivered on the decoder thread.
- std::vector<DecodedFrame> decoded_frames_;
};
MediaCodecVideoDecoder::MediaCodecVideoDecoder(
@@ -209,7 +180,6 @@ MediaCodecVideoDecoder::MediaCodecVideoDecoder(
key_frame_required_(true),
inited_(false),
sw_fallback_required_(false),
- codec_thread_(new Thread()),
j_media_codec_video_decoder_class_(
jni,
FindClass(jni, "org/webrtc/MediaCodecVideoDecoder")),
@@ -220,8 +190,7 @@ MediaCodecVideoDecoder::MediaCodecVideoDecoder(
*j_media_codec_video_decoder_class_,
"<init>",
"()V"))) {
- codec_thread_->SetName("MediaCodecVideoDecoder", NULL);
- RTC_CHECK(codec_thread_->Start());
+ decode_thread_checker_.DetachFromThread();
j_init_decode_method_ = GetMethodID(
jni, *j_media_codec_video_decoder_class_, "initDecode",
@@ -310,6 +279,7 @@ MediaCodecVideoDecoder::~MediaCodecVideoDecoder() {
int32_t MediaCodecVideoDecoder::InitDecode(const VideoCodec* inst,
int32_t numberOfCores) {
+ RTC_DCHECK(decode_thread_checker_.CalledOnValidThread());
ALOGD << "InitDecode.";
if (inst == NULL) {
ALOGE << "NULL VideoCodec instance";
@@ -331,13 +301,11 @@ int32_t MediaCodecVideoDecoder::InitDecode(const VideoCodec* inst,
codec_.maxFramerate = (codec_.maxFramerate >= 1) ? codec_.maxFramerate : 30;
// Call Java init.
- return codec_thread_->Invoke<int32_t>(
- RTC_FROM_HERE,
- Bind(&MediaCodecVideoDecoder::InitDecodeOnCodecThread, this));
+ return InitDecodeInternal();
}
void MediaCodecVideoDecoder::ResetVariables() {
- RTC_DCHECK(IsOnCodecThread());
+ RTC_DCHECK(decode_thread_checker_.CalledOnValidThread());
key_frame_required_ = true;
frames_received_ = 0;
@@ -351,16 +319,16 @@ void MediaCodecVideoDecoder::ResetVariables() {
pending_frame_qps_.clear();
}
-int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() {
- RTC_DCHECK(IsOnCodecThread());
+int32_t MediaCodecVideoDecoder::InitDecodeInternal() {
+ RTC_DCHECK(decode_thread_checker_.CalledOnValidThread());
JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni);
- ALOGD << "InitDecodeOnCodecThread Type: " << (int)codecType_ << ". "
- << codec_.width << " x " << codec_.height << ". Fps: " <<
- (int)codec_.maxFramerate;
+ ALOGD << "InitDecodeInternal Type: " << (int)codecType_ << ". "
+ << codec_.width << " x " << codec_.height
+ << ". Fps: " << (int)codec_.maxFramerate;
// Release previous codec first if it was allocated before.
- int ret_val = ReleaseOnCodecThread();
+ int ret_val = Release();
if (ret_val < 0) {
ALOGE << "Release failure: " << ret_val << " - fallback to SW codec";
sw_fallback_required_ = true;
@@ -429,12 +397,12 @@ int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() {
return WEBRTC_VIDEO_CODEC_OK;
}
-int32_t MediaCodecVideoDecoder::ResetDecodeOnCodecThread() {
- RTC_DCHECK(IsOnCodecThread());
+int32_t MediaCodecVideoDecoder::ResetDecode() {
+ RTC_DCHECK(decode_thread_checker_.CalledOnValidThread());
JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni);
- ALOGD << "ResetDecodeOnCodecThread Type: " << (int)codecType_ << ". "
- << codec_.width << " x " << codec_.height;
+ ALOGD << "ResetDecode Type: " << (int)codecType_ << ". " << codec_.width
+ << " x " << codec_.height;
ALOGD << " Frames received: " << frames_received_ <<
". Frames decoded: " << frames_decoded_;
@@ -459,18 +427,12 @@ int32_t MediaCodecVideoDecoder::ResetDecodeOnCodecThread() {
int32_t MediaCodecVideoDecoder::Release() {
ALOGD << "DecoderRelease request";
- return codec_thread_->Invoke<int32_t>(
- RTC_FROM_HERE, Bind(&MediaCodecVideoDecoder::ReleaseOnCodecThread, this));
-}
-
-int32_t MediaCodecVideoDecoder::ReleaseOnCodecThread() {
- RTC_DCHECK(IsOnCodecThread());
if (!inited_) {
return WEBRTC_VIDEO_CODEC_OK;
}
JNIEnv* jni = AttachCurrentThreadIfNeeded();
- ALOGD << "DecoderReleaseOnCodecThread: Frames received: " <<
- frames_received_ << ". Frames decoded: " << frames_decoded_;
+ ALOGD << "DecoderRelease: Frames received: " << frames_received_
+ << ". Frames decoded: " << frames_decoded_;
ScopedLocalRefFrame local_ref_frame(jni);
for (size_t i = 0; i < input_buffers_.size(); i++) {
jni->DeleteGlobalRef(input_buffers_[i]);
@@ -483,14 +445,10 @@ int32_t MediaCodecVideoDecoder::ReleaseOnCodecThread() {
ALOGE << "Decoder release exception";
return WEBRTC_VIDEO_CODEC_ERROR;
}
- ALOGD << "DecoderReleaseOnCodecThread done";
+ ALOGD << "DecoderRelease done";
return WEBRTC_VIDEO_CODEC_OK;
}
-bool MediaCodecVideoDecoder::IsOnCodecThread() {
- return codec_thread_.get() == ThreadManager::Instance()->CurrentThread();
-}
-
void MediaCodecVideoDecoder::EnableFrameLogOnWarning() {
// Log next 2 output frames.
static const int kMaxWarningLogFrames = 2;
@@ -498,16 +456,16 @@ void MediaCodecVideoDecoder::EnableFrameLogOnWarning() {
frames_decoded_logged_, frames_decoded_ + kMaxWarningLogFrames);
}
-int32_t MediaCodecVideoDecoder::ProcessHWErrorOnCodecThread() {
- RTC_DCHECK(IsOnCodecThread());
- int ret_val = ReleaseOnCodecThread();
+int32_t MediaCodecVideoDecoder::ProcessHWError() {
+ RTC_DCHECK(decode_thread_checker_.CalledOnValidThread());
+ int ret_val = Release();
if (ret_val < 0) {
ALOGE << "ProcessHWError: Release failure";
}
if (codecType_ == kVideoCodecH264) {
// For now there is no SW H.264 which can be used as fallback codec.
// So try to restart hw codec for now.
- ret_val = InitDecodeOnCodecThread();
+ ret_val = InitDecodeInternal();
ALOGE << "Reset H.264 codec done. Status: " << ret_val;
if (ret_val == WEBRTC_VIDEO_CODEC_OK) {
// H.264 codec was succesfully reset - return regular error code.
@@ -530,6 +488,7 @@ int32_t MediaCodecVideoDecoder::Decode(
const RTPFragmentationHeader* fragmentation,
const CodecSpecificInfo* codecSpecificInfo,
int64_t renderTimeMs) {
+ RTC_DCHECK(decode_thread_checker_.CalledOnValidThread());
RTC_DCHECK(callback_);
RTC_DCHECK(inited_);
@@ -555,9 +514,7 @@ int32_t MediaCodecVideoDecoder::Decode(
if (use_surface_ &&
(codecType_ == kVideoCodecVP8 || codecType_ == kVideoCodecH264)) {
// Soft codec reset - only for surface decoding.
- ret = codec_thread_->Invoke<int32_t>(
- RTC_FROM_HERE,
- Bind(&MediaCodecVideoDecoder::ResetDecodeOnCodecThread, this));
+ ret = ResetDecode();
} else {
// Hard codec reset.
ret = InitDecode(&codec_, 1);
@@ -585,32 +542,7 @@ int32_t MediaCodecVideoDecoder::Decode(
return WEBRTC_VIDEO_CODEC_ERROR;
}
- std::vector<DecodedFrame> frames;
- int32_t ret = codec_thread_->Invoke<int32_t>(
- RTC_FROM_HERE, Bind(&MediaCodecVideoDecoder::DecodeOnCodecThread, this,
- inputImage, &frames));
- for (auto& f : frames)
- callback_->Decoded(f.frame, rtc::Optional<int32_t>(f.decode_time_ms), f.qp);
- return ret;
-}
-
-void MediaCodecVideoDecoder::PollDecodedFrames() {
- RTC_DCHECK(callback_);
-
- std::vector<DecodedFrame> frames;
- codec_thread_->Invoke<void>(
- RTC_FROM_HERE,
- Bind(&MediaCodecVideoDecoder::PollDecodedFramesOnCodecThread, this,
- &frames));
-
- for (auto& f : frames)
- callback_->Decoded(f.frame, rtc::Optional<int32_t>(f.decode_time_ms), f.qp);
-}
-
-int32_t MediaCodecVideoDecoder::DecodeOnCodecThread(
- const EncodedImage& inputImage,
- std::vector<DecodedFrame>* frames) {
- RTC_DCHECK(IsOnCodecThread());
+ RTC_DCHECK(decode_thread_checker_.CalledOnValidThread());
JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni);
@@ -626,16 +558,16 @@ int32_t MediaCodecVideoDecoder::DecodeOnCodecThread(
const int64 drain_start = rtc::TimeMillis();
while ((frames_received_ > frames_decoded_ + max_pending_frames_) &&
(rtc::TimeMillis() - drain_start) < kMediaCodecTimeoutMs) {
- if (!DeliverPendingOutputs(jni, kMediaCodecPollMs, frames)) {
+ if (!DeliverPendingOutputs(jni, kMediaCodecPollMs)) {
ALOGE << "DeliverPendingOutputs error. Frames received: " <<
frames_received_ << ". Frames decoded: " << frames_decoded_;
- return ProcessHWErrorOnCodecThread();
+ return ProcessHWError();
}
}
if (frames_received_ > frames_decoded_ + max_pending_frames_) {
ALOGE << "Output buffer dequeue timeout. Frames received: " <<
frames_received_ << ". Frames decoded: " << frames_decoded_;
- return ProcessHWErrorOnCodecThread();
+ return ProcessHWError();
}
// Get input buffer.
@@ -646,17 +578,17 @@ int32_t MediaCodecVideoDecoder::DecodeOnCodecThread(
". Retry DeliverPendingOutputs.";
EnableFrameLogOnWarning();
// Try to drain the decoder.
- if (!DeliverPendingOutputs(jni, kMediaCodecPollMs, frames)) {
+ if (!DeliverPendingOutputs(jni, kMediaCodecPollMs)) {
ALOGE << "DeliverPendingOutputs error. Frames received: " <<
frames_received_ << ". Frames decoded: " << frames_decoded_;
- return ProcessHWErrorOnCodecThread();
+ return ProcessHWError();
}
// Try dequeue input buffer one last time.
j_input_buffer_index = jni->CallIntMethod(
*j_media_codec_video_decoder_, j_dequeue_input_buffer_method_);
if (CheckException(jni) || j_input_buffer_index < 0) {
ALOGE << "dequeueInputBuffer critical error: " << j_input_buffer_index;
- return ProcessHWErrorOnCodecThread();
+ return ProcessHWError();
}
}
@@ -669,7 +601,7 @@ int32_t MediaCodecVideoDecoder::DecodeOnCodecThread(
if (CheckException(jni) || buffer_capacity < inputImage._length) {
ALOGE << "Input frame size "<< inputImage._length <<
" is bigger than buffer size " << buffer_capacity;
- return ProcessHWErrorOnCodecThread();
+ return ProcessHWError();
}
jlong presentation_timestamp_us = static_cast<jlong>(
static_cast<int64_t>(frames_received_) * 1000000 / codec_.maxFramerate);
@@ -713,37 +645,33 @@ int32_t MediaCodecVideoDecoder::DecodeOnCodecThread(
inputImage.ntp_time_ms_);
if (CheckException(jni) || !success) {
ALOGE << "queueInputBuffer error";
- return ProcessHWErrorOnCodecThread();
+ return ProcessHWError();
}
// Try to drain the decoder
- if (!DeliverPendingOutputs(jni, 0, frames)) {
+ if (!DeliverPendingOutputs(jni, 0)) {
ALOGE << "DeliverPendingOutputs error";
- return ProcessHWErrorOnCodecThread();
+ return ProcessHWError();
}
return WEBRTC_VIDEO_CODEC_OK;
}
-void MediaCodecVideoDecoder::PollDecodedFramesOnCodecThread(
- std::vector<DecodedFrame>* frames) {
- RTC_DCHECK(IsOnCodecThread());
+void MediaCodecVideoDecoder::PollDecodedFrames() {
+ RTC_DCHECK(decode_thread_checker_.CalledOnValidThread());
JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni);
- if (!DeliverPendingOutputs(jni, 0, frames)) {
- ALOGE << "PollDecodedFramesOnCodecThread: DeliverPendingOutputs error";
- ProcessHWErrorOnCodecThread();
+ if (!DeliverPendingOutputs(jni, 0)) {
+ ALOGE << "PollDecodedFrames: DeliverPendingOutputs error";
+ ProcessHWError();
}
}
-bool MediaCodecVideoDecoder::DeliverPendingOutputs(
- JNIEnv* jni,
- int dequeue_timeout_ms,
- std::vector<DecodedFrame>* frames) {
- RTC_DCHECK(IsOnCodecThread());
- RTC_DCHECK(frames);
+bool MediaCodecVideoDecoder::DeliverPendingOutputs(JNIEnv* jni,
+ int dequeue_timeout_ms) {
+ RTC_DCHECK(decode_thread_checker_.CalledOnValidThread());
if (frames_received_ <= frames_decoded_) {
// No need to query for output buffers - decoder is drained.
@@ -954,16 +882,10 @@ bool MediaCodecVideoDecoder::DeliverPendingOutputs(
rtc::Optional<uint8_t> qp = pending_frame_qps_.front();
pending_frame_qps_.pop_front();
- decoded_frames_.push_back(DecodedFrame(std::move(decoded_frame),
- decode_time_ms, output_timestamps_ms,
- output_ntp_timestamps_ms, qp));
+ callback_->Decoded(decoded_frame, rtc::Optional<int32_t>(decode_time_ms),
+ qp);
}
- frames->reserve(frames->size() + decoded_frames_.size());
- std::move(decoded_frames_.begin(), decoded_frames_.end(),
- std::back_inserter(*frames));
- decoded_frames_.clear();
-
return true;
}
« no previous file with comments | « webrtc/sdk/android/api/org/webrtc/MediaCodecVideoDecoder.java ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698