in streaming/screen-sharing-agent/app/src/main/cpp/display_streamer.cc [208:335]
void DisplayStreamer::Run() {
Jni jni = Jvm::GetJni();
WindowManager::WatchRotation(jni, display_id_, &display_rotation_watcher_);
// Don't listen to display events on non-foldable HONOR phones. HONOR 90 is producing bogus display change events (b/348562991).
if (!DeviceStateManager::GetSupportedDeviceStates(jni).empty() || Agent::device_manufacturer() != HONOR) {
DisplayManager::AddDisplayListener(jni, this);
}
AMediaFormat* media_format = CreateMediaFormat(codec_info_->mime_type);
VideoPacketHeader packet_header = { .display_id = display_id_, .frame_number = frame_number_};
FrameStreamStopReason stop_reason = FrameStreamStopReason::CODEC_STOPPED;
int error_count = 0;
while (stop_reason != FrameStreamStopReason::END_OF_STREAM && !streamer_stopped_ && !Agent::IsShuttingDown()) {
DisplayInfo display_info = DisplayManager::GetDisplayInfo(jni, display_id_);
if (display_id_ != PRIMARY_DISPLAY_ID && (!display_info.IsValid() || !display_info.IsOn())) {
Log::W("Display %d: turned off", display_id_);
DisplayManager::OnDisplayRemoved(jni, display_id_);
break;
}
Log::D("Display %d: display_info: %s", display_id_, display_info.ToDebugString().c_str());
if (stop_reason != FrameStreamStopReason::TIMEOUT) {
ReleaseVirtualDisplay(jni);
}
if (virtual_display_.IsNull() && display_token_.IsNull()) {
string display_name = StringPrintf("studio.screen.sharing:%d", display_id_);
if (Agent::feature_level() >= 34) {
virtual_display_ = DisplayManager::CreateVirtualDisplay(
jni, display_name.c_str(), display_info.logical_size.width, display_info.logical_size.height, display_id_, nullptr);
} else {
bool secure = Agent::feature_level() < 31; // Creation of secure displays is not allowed on API 31+.
display_token_ = SurfaceControl::CreateDisplay(jni, display_name.c_str(), secure);
if (display_token_.IsNull()) {
Log::Fatal(VIRTUAL_DISPLAY_CREATION_ERROR, "Display %d: unable to create a virtual display", display_id_);
}
}
}
{
unique_lock lock(mutex_);
if (codec_stop_pending_) {
codec_stop_pending_ = false;
ReleaseVirtualDisplay(jni);
continue; // Start another loop to refresh display information.
}
display_info_ = display_info;
int32_t rotation_correction = video_orientation_ >= 0 ? NormalizeRotation(video_orientation_ - display_info.rotation) : 0;
if (display_info.rotation == 2 && rotation_correction == 0 && Agent::device_type() != DeviceType::WATCH) {
// Simulated rotation is not capable of distinguishing between regular and upside down
// display orientation. Compensate for that using rotation_correction.
display_info.rotation = 0;
rotation_correction = 2;
}
CreateCodec();
Size video_size = ConfigureCodec(
codec_, *codec_info_, max_video_resolution_.Rotated(rotation_correction), bit_rate_, media_format, display_info, display_id_);
Log::D("Display %d: rotation=%d rotation_correction=%d video_size=%dx%d",
display_id_, display_info.rotation, rotation_correction, video_size.width, video_size.height);
media_status_t status = AMediaCodec_createInputSurface(codec_, &surface_); // Requires API 26.
if (status != AMEDIA_OK) {
Log::Fatal(INPUT_SURFACE_CREATION_ERROR, "Display %d: AMediaCodec_createInputSurface returned %d", display_id_, status);
}
if (Agent::feature_level() >= 34) {
virtual_display_.Resize(video_size.width, video_size.height, display_info_.logical_density_dpi);
virtual_display_.SetSurface(surface_);
} else {
int32_t height = lround(static_cast<double>(video_size.width) * display_info.logical_size.height / display_info.logical_size.width);
int32_t y = (video_size.height - height) / 2;
SurfaceControl::ConfigureProjection(jni, display_token_, surface_, display_info, { 0, y, video_size.width, height });
}
StartCodecUnlocked();
codec_running_ = true;
Size display_size = display_info.NaturalSize(); // The display dimensions in the canonical orientation.
packet_header.display_width = display_size.width;
packet_header.display_height = display_size.height;
packet_header.display_orientation = NormalizeRotation(display_info.rotation + rotation_correction);
packet_header.display_orientation_correction = NormalizeRotation(rotation_correction);
packet_header.flags =
((display_info.flags & DisplayInfo::FLAG_ROUND) ? VideoPacketHeader::FLAG_DISPLAY_ROUND : 0) | // NOLINT(*-narrowing-conversions)
(bit_rate_reduced_ ? VideoPacketHeader::FLAG_BIT_RATE_REDUCED : 0);
packet_header.bit_rate = bit_rate_;
}
AMediaFormat* sync_frame_request = AMediaFormat_new();
AMediaFormat_setInt32(sync_frame_request, AMEDIACODEC_KEY_REQUEST_SYNC_FRAME, 0);
stop_reason = ProcessFramesUntilCodecStopped(&packet_header, sync_frame_request);
Log::D("ProcessFramesUntilCodecStopped returned %d", stop_reason);
AMediaFormat_delete(sync_frame_request);
StopCodec();
DeleteCodec();
if (virtual_display_.IsNotNull()) {
virtual_display_.SetSurface(nullptr);
} else {
SurfaceControl::SetSurface(jni, display_token_, nullptr);
}
ANativeWindow_release(surface_);
surface_ = nullptr;
if (stop_reason == FrameStreamStopReason::CODEC_ERROR) {
if (++error_count >= MAX_SUBSEQUENT_ERRORS && !ReduceBitRate()) {
ExitCode exitCode = bit_rate_ <= MIN_BIT_RATE ? WEAK_VIDEO_ENCODER : REPEATED_VIDEO_ENCODER_ERRORS;
Log::Fatal(exitCode, "Display %d: too many video encoder errors:\n%s", display_id_,
GetVideoEncoderDetails(*codec_info_, packet_header.display_width, packet_header.display_height).c_str());
}
} else {
error_count = 0;
if (stop_reason == FrameStreamStopReason::TIMEOUT) {
// Write an empty video packet.
int64_t timestamp = duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
packet_header.origination_timestamp_us = timestamp;
packet_header.packet_size = 0;
if (Log::IsEnabled(Log::Level::VERBOSE)) {
Log::V("Display %d: writing an video packet", display_id_);
}
auto res = writer_->Write(&packet_header, VideoPacketHeader::SIZE);
if (res == SocketWriter::Result::DISCONNECTED) {
stop_reason = FrameStreamStopReason::END_OF_STREAM;
}
}
}
}
ReleaseVirtualDisplay(jni);
AMediaFormat_delete(media_format);
WindowManager::RemoveRotationWatcher(jni, display_id_, &display_rotation_watcher_);
DisplayManager::RemoveDisplayListener(this);
if (stop_reason == FrameStreamStopReason::END_OF_STREAM) {
Agent::Shutdown();
}
}