Implement QP parsing in VideoDecoderWrapper.
BUG=webrtc:7760 NOTRY=True Review-Url: https://codereview.webrtc.org/3000993002 Cr-Commit-Position: refs/heads/master@{#19378}
This commit is contained in:
@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
#include "webrtc/api/video/video_frame.h"
|
#include "webrtc/api/video/video_frame.h"
|
||||||
#include "webrtc/modules/video_coding/include/video_codec_interface.h"
|
#include "webrtc/modules/video_coding/include/video_codec_interface.h"
|
||||||
|
#include "webrtc/modules/video_coding/utility/vp8_header_parser.h"
|
||||||
|
#include "webrtc/modules/video_coding/utility/vp9_uncompressed_header_parser.h"
|
||||||
#include "webrtc/rtc_base/logging.h"
|
#include "webrtc/rtc_base/logging.h"
|
||||||
#include "webrtc/sdk/android/src/jni/classreferenceholder.h"
|
#include "webrtc/sdk/android/src/jni/classreferenceholder.h"
|
||||||
|
|
||||||
@ -70,6 +72,8 @@ VideoDecoderWrapper::VideoDecoderWrapper(JNIEnv* jni, jobject decoder)
|
|||||||
int_value_method_ = jni->GetMethodID(*integer_class_, "intValue", "()I");
|
int_value_method_ = jni->GetMethodID(*integer_class_, "intValue", "()I");
|
||||||
|
|
||||||
initialized_ = false;
|
initialized_ = false;
|
||||||
|
// QP parsing starts enabled and we disable it if the decoder provides frames.
|
||||||
|
qp_parsing_enabled_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t VideoDecoderWrapper::InitDecode(
|
int32_t VideoDecoderWrapper::InitDecode(
|
||||||
@ -100,6 +104,11 @@ int32_t VideoDecoderWrapper::InitDecodeInternal(JNIEnv* jni) {
|
|||||||
if (jni->CallIntMethod(ret, get_number_method_) == WEBRTC_VIDEO_CODEC_OK) {
|
if (jni->CallIntMethod(ret, get_number_method_) == WEBRTC_VIDEO_CODEC_OK) {
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The decoder was reinitialized so re-enable the QP parsing in case it stops
|
||||||
|
// providing QP values.
|
||||||
|
qp_parsing_enabled_ = true;
|
||||||
|
|
||||||
return HandleReturnCode(jni, ret);
|
return HandleReturnCode(jni, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,6 +129,8 @@ int32_t VideoDecoderWrapper::Decode(
|
|||||||
FrameExtraInfo frame_extra_info;
|
FrameExtraInfo frame_extra_info;
|
||||||
frame_extra_info.capture_time_ms = input_image.capture_time_ms_;
|
frame_extra_info.capture_time_ms = input_image.capture_time_ms_;
|
||||||
frame_extra_info.timestamp_rtp = input_image._timeStamp;
|
frame_extra_info.timestamp_rtp = input_image._timeStamp;
|
||||||
|
frame_extra_info.qp =
|
||||||
|
qp_parsing_enabled_ ? ParseQP(input_image) : rtc::Optional<uint8_t>();
|
||||||
frame_extra_infos_.push_back(frame_extra_info);
|
frame_extra_infos_.push_back(frame_extra_info);
|
||||||
|
|
||||||
jobject jinput_image =
|
jobject jinput_image =
|
||||||
@ -189,9 +200,16 @@ void VideoDecoderWrapper::OnDecodedFrame(JNIEnv* jni,
|
|||||||
rtc::Optional<uint8_t> qp;
|
rtc::Optional<uint8_t> qp;
|
||||||
if (jqp != nullptr) {
|
if (jqp != nullptr) {
|
||||||
qp = rtc::Optional<uint8_t>(jni->CallIntMethod(jqp, int_value_method_));
|
qp = rtc::Optional<uint8_t>(jni->CallIntMethod(jqp, int_value_method_));
|
||||||
|
// The decoder provides QP values itself, no need to parse the bitstream.
|
||||||
|
qp_parsing_enabled_ = false;
|
||||||
|
} else {
|
||||||
|
qp = frame_extra_info.qp;
|
||||||
|
// The decoder doesn't provide QP values, ensure bitstream parsing is
|
||||||
|
// enabled.
|
||||||
|
qp_parsing_enabled_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback_->Decoded(frame, decoding_time_ms, rtc::Optional<uint8_t>());
|
callback_->Decoded(frame, decoding_time_ms, qp);
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject VideoDecoderWrapper::ConvertEncodedImageToJavaEncodedImage(
|
jobject VideoDecoderWrapper::ConvertEncodedImageToJavaEncodedImage(
|
||||||
@ -242,6 +260,45 @@ int32_t VideoDecoderWrapper::HandleReturnCode(JNIEnv* jni, jobject code) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc::Optional<uint8_t> VideoDecoderWrapper::ParseQP(
|
||||||
|
const webrtc::EncodedImage& input_image) {
|
||||||
|
if (input_image.qp_ != -1) {
|
||||||
|
return rtc::Optional<uint8_t>(input_image.qp_);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc::Optional<uint8_t> qp;
|
||||||
|
switch (codec_settings_.codecType) {
|
||||||
|
case webrtc::kVideoCodecVP8: {
|
||||||
|
int qp_int;
|
||||||
|
if (webrtc::vp8::GetQp(input_image._buffer, input_image._length,
|
||||||
|
&qp_int)) {
|
||||||
|
qp = rtc::Optional<uint8_t>(qp_int);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case webrtc::kVideoCodecVP9: {
|
||||||
|
int qp_int;
|
||||||
|
if (webrtc::vp9::GetQp(input_image._buffer, input_image._length,
|
||||||
|
&qp_int)) {
|
||||||
|
qp = rtc::Optional<uint8_t>(qp_int);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case webrtc::kVideoCodecH264: {
|
||||||
|
h264_bitstream_parser_.ParseBitstream(input_image._buffer,
|
||||||
|
input_image._length);
|
||||||
|
int qp_int;
|
||||||
|
if (h264_bitstream_parser_.GetLastSliceQp(&qp_int)) {
|
||||||
|
qp = rtc::Optional<uint8_t>(qp_int);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break; // Default is to not provide QP.
|
||||||
|
}
|
||||||
|
return qp;
|
||||||
|
}
|
||||||
|
|
||||||
JOW(void, VideoDecoderWrapperCallback_nativeOnDecodedFrame)
|
JOW(void, VideoDecoderWrapperCallback_nativeOnDecodedFrame)
|
||||||
(JNIEnv* jni,
|
(JNIEnv* jni,
|
||||||
jclass,
|
jclass,
|
||||||
|
|||||||
@ -12,10 +12,10 @@
|
|||||||
#define WEBRTC_SDK_ANDROID_SRC_JNI_VIDEODECODERWRAPPER_H_
|
#define WEBRTC_SDK_ANDROID_SRC_JNI_VIDEODECODERWRAPPER_H_
|
||||||
|
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
#include "webrtc/api/video_codecs/video_decoder.h"
|
#include "webrtc/api/video_codecs/video_decoder.h"
|
||||||
|
#include "webrtc/common_video/h264/h264_bitstream_parser.h"
|
||||||
#include "webrtc/sdk/android/src/jni/jni_helpers.h"
|
#include "webrtc/sdk/android/src/jni/jni_helpers.h"
|
||||||
#include "webrtc/sdk/android/src/jni/native_handle_impl.h"
|
#include "webrtc/sdk/android/src/jni/native_handle_impl.h"
|
||||||
|
|
||||||
@ -60,6 +60,7 @@ class VideoDecoderWrapper : public webrtc::VideoDecoder {
|
|||||||
uint32_t capture_time_ms; // Used as an identifier of the frame.
|
uint32_t capture_time_ms; // Used as an identifier of the frame.
|
||||||
|
|
||||||
uint32_t timestamp_rtp;
|
uint32_t timestamp_rtp;
|
||||||
|
rtc::Optional<uint8_t> qp;
|
||||||
};
|
};
|
||||||
|
|
||||||
int32_t InitDecodeInternal(JNIEnv* jni);
|
int32_t InitDecodeInternal(JNIEnv* jni);
|
||||||
@ -68,12 +69,16 @@ class VideoDecoderWrapper : public webrtc::VideoDecoder {
|
|||||||
// status code.
|
// status code.
|
||||||
int32_t HandleReturnCode(JNIEnv* jni, jobject code);
|
int32_t HandleReturnCode(JNIEnv* jni, jobject code);
|
||||||
|
|
||||||
|
rtc::Optional<uint8_t> ParseQP(const webrtc::EncodedImage& input_image);
|
||||||
|
|
||||||
webrtc::VideoCodec codec_settings_;
|
webrtc::VideoCodec codec_settings_;
|
||||||
int32_t number_of_cores_;
|
int32_t number_of_cores_;
|
||||||
|
|
||||||
bool initialized_;
|
bool initialized_;
|
||||||
AndroidVideoBufferFactory android_video_buffer_factory_;
|
AndroidVideoBufferFactory android_video_buffer_factory_;
|
||||||
std::deque<FrameExtraInfo> frame_extra_infos_;
|
std::deque<FrameExtraInfo> frame_extra_infos_;
|
||||||
|
bool qp_parsing_enabled_;
|
||||||
|
webrtc::H264BitstreamParser h264_bitstream_parser_;
|
||||||
|
|
||||||
webrtc::DecodedImageCallback* callback_;
|
webrtc::DecodedImageCallback* callback_;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user