This CL extends our support for injecting native codecs such that
downstream users can create Java codecs that are backed by custom
native codecs.
After this CL, the Java codec interfaces expose
createNativeVideo{En,Decoder}() methods that may return a value
representing a pointer to the backing native codec. Previously,
a similar mechanism was used for the special case of non-public
Java codecs extending from the internal
WrappedNativeVideo{En,De}coder classes.
Tested: AppRTCMobile on Pixel XL and Pixel 2.
Bug: webrtc:9495
Change-Id: I079ff744afc7bf9873ff983e775c136a6667266d
Reviewed-on: https://webrtc-review.googlesource.com/87264
Commit-Queue: Rasmus Brandt <brandtr@webrtc.org>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23883}
124 lines
4.3 KiB
C++
124 lines
4.3 KiB
C++
/*
|
|
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#ifndef SDK_ANDROID_SRC_JNI_VIDEODECODERWRAPPER_H_
|
|
#define SDK_ANDROID_SRC_JNI_VIDEODECODERWRAPPER_H_
|
|
|
|
#include <jni.h>
|
|
#include <atomic>
|
|
#include <deque>
|
|
|
|
#include "api/video_codecs/video_decoder.h"
|
|
#include "common_video/h264/h264_bitstream_parser.h"
|
|
#include "rtc_base/race_checker.h"
|
|
#include "rtc_base/thread_checker.h"
|
|
#include "sdk/android/src/jni/jni_helpers.h"
|
|
|
|
namespace webrtc {
|
|
namespace jni {
|
|
|
|
// Wraps a Java decoder and delegates all calls to it.
|
|
class VideoDecoderWrapper : public VideoDecoder {
|
|
public:
|
|
VideoDecoderWrapper(JNIEnv* jni, const JavaRef<jobject>& decoder);
|
|
~VideoDecoderWrapper() override;
|
|
|
|
int32_t InitDecode(const VideoCodec* codec_settings,
|
|
int32_t number_of_cores) override;
|
|
|
|
int32_t Decode(const EncodedImage& input_image,
|
|
bool missing_frames,
|
|
const CodecSpecificInfo* codec_specific_info,
|
|
int64_t render_time_ms) override;
|
|
|
|
int32_t RegisterDecodeCompleteCallback(
|
|
DecodedImageCallback* callback) override;
|
|
|
|
// TODO(sakal): This is not always called on the correct thread. It is called
|
|
// from VCMGenericDecoder destructor which is on a different thread but is
|
|
// still safe and synchronous.
|
|
int32_t Release() override RTC_NO_THREAD_SAFETY_ANALYSIS;
|
|
|
|
// Returns true if the decoder prefer to decode frames late.
|
|
// That is, it can not decode infinite number of frames before the decoded
|
|
// frame is consumed.
|
|
bool PrefersLateDecoding() const override;
|
|
|
|
const char* ImplementationName() const override;
|
|
|
|
// Wraps the frame to a AndroidVideoBuffer and passes it to the callback.
|
|
void OnDecodedFrame(JNIEnv* env,
|
|
const JavaRef<jobject>& j_caller,
|
|
const JavaRef<jobject>& j_frame,
|
|
const JavaRef<jobject>& j_decode_time_ms,
|
|
const JavaRef<jobject>& j_qp);
|
|
|
|
private:
|
|
struct FrameExtraInfo {
|
|
int64_t timestamp_ns; // Used as an identifier of the frame.
|
|
|
|
uint32_t timestamp_rtp;
|
|
int64_t timestamp_ntp;
|
|
absl::optional<uint8_t> qp;
|
|
|
|
FrameExtraInfo();
|
|
FrameExtraInfo(const FrameExtraInfo&);
|
|
~FrameExtraInfo();
|
|
};
|
|
|
|
int32_t InitDecodeInternal(JNIEnv* jni) RTC_RUN_ON(decoder_thread_checker_);
|
|
|
|
// Takes Java VideoCodecStatus, handles it and returns WEBRTC_VIDEO_CODEC_*
|
|
// status code.
|
|
int32_t HandleReturnCode(JNIEnv* jni,
|
|
const JavaRef<jobject>& j_value,
|
|
const char* method_name)
|
|
RTC_RUN_ON(decoder_thread_checker_);
|
|
|
|
absl::optional<uint8_t> ParseQP(const EncodedImage& input_image)
|
|
RTC_RUN_ON(decoder_thread_checker_);
|
|
|
|
const ScopedJavaGlobalRef<jobject> decoder_;
|
|
const std::string implementation_name_;
|
|
|
|
rtc::ThreadChecker decoder_thread_checker_;
|
|
// Callbacks must be executed sequentially on an arbitrary thread. We do not
|
|
// own this thread so a thread checker cannot be used.
|
|
rtc::RaceChecker callback_race_checker_;
|
|
|
|
// Initialized on InitDecode and immutable after that.
|
|
VideoCodec codec_settings_ RTC_GUARDED_BY(decoder_thread_checker_);
|
|
int32_t number_of_cores_ RTC_GUARDED_BY(decoder_thread_checker_);
|
|
|
|
bool initialized_ RTC_GUARDED_BY(decoder_thread_checker_);
|
|
H264BitstreamParser h264_bitstream_parser_
|
|
RTC_GUARDED_BY(decoder_thread_checker_);
|
|
|
|
DecodedImageCallback* callback_ RTC_GUARDED_BY(callback_race_checker_);
|
|
|
|
// Accessed both on the decoder thread and the callback thread.
|
|
std::atomic<bool> qp_parsing_enabled_;
|
|
rtc::CriticalSection frame_extra_infos_lock_;
|
|
std::deque<FrameExtraInfo> frame_extra_infos_
|
|
RTC_GUARDED_BY(frame_extra_infos_lock_);
|
|
};
|
|
|
|
/* If the j_decoder is a wrapped native decoder, unwrap it. If it is not,
|
|
* wrap it in a VideoDecoderWrapper.
|
|
*/
|
|
std::unique_ptr<VideoDecoder> JavaToNativeVideoDecoder(
|
|
JNIEnv* jni,
|
|
const JavaRef<jobject>& j_decoder);
|
|
|
|
} // namespace jni
|
|
} // namespace webrtc
|
|
|
|
#endif // SDK_ANDROID_SRC_JNI_VIDEODECODERWRAPPER_H_
|