diff --git a/sdk/ohos/api/ets/xcomponent/VideoRenderController.ets b/sdk/ohos/api/ets/xcomponent/VideoRenderController.ets index 03bdd02a7b75a65094998dcd9c395fb768d3872b..22e740289f4764ad0771dd2b5cdbffed6d4c8893 100644 --- a/sdk/ohos/api/ets/xcomponent/VideoRenderController.ets +++ b/sdk/ohos/api/ets/xcomponent/VideoRenderController.ets @@ -18,6 +18,8 @@ import { Logging } from '../log/Logging' const TAG: string = '[XComponentController1]'; +export enum ScalingMode { Fill, AspectFill, AspectFit } + export class VideoRenderController extends XComponentController { private renderer: NativeVideoRenderer = new NativeVideoRenderer(); @@ -25,6 +27,18 @@ export class VideoRenderController extends XComponentController { this.renderer.setVideoTrack(track); } + setMirror(mirror: boolean) : void { + this.renderer.setMirror(mirror); + } + + setMirrorVertically(mirrorVertically: boolean): void { + this.renderer.setMirrorVertically(mirrorVertically); + } + + setScalingMode(mode: ScalingMode) : void { + this.renderer.setScalingMode(mode); + } + onSurfaceCreated(surfaceId: string): void { Logging.d(TAG, 'onSurfaceCreated surfaceId: ' + surfaceId); this.renderer.init(surfaceId); diff --git a/sdk/ohos/api/libohos_webrtc/webrtc.d.ts b/sdk/ohos/api/libohos_webrtc/webrtc.d.ts index faf6d559ac920580b3f3733c77a8340314c46e8f..0e54bef2c022420124e6c1aac979033e5584d3f5 100644 --- a/sdk/ohos/api/libohos_webrtc/webrtc.d.ts +++ b/sdk/ohos/api/libohos_webrtc/webrtc.d.ts @@ -841,6 +841,9 @@ export interface NativeVideoRenderer { init(surfaceId: string): void; setVideoTrack(videoTrack: MediaStreamTrack | null): void; + setMirror(mirrorHorizontally: boolean): void; + setMirrorVertically(mirrorVertically: boolean): void; + setScalingMode(mode: number): void; release(): void; } diff --git a/sdk/ohos/api/libwebrtc.md b/sdk/ohos/api/libwebrtc.md index 77dd36a6c03bf3a95f0eb04a67285c9d030f8e15..7b2ac43c246a449d374bfa193c623e7274776a4b 100644 --- a/sdk/ohos/api/libwebrtc.md +++ b/sdk/ohos/api/libwebrtc.md @@ -2576,8 +2576,8 @@ logMessage(message: string, severity: number, tag: string): void; | 名称 | 类型 | 可读 | 可写 | 说明 | |--------------|-------------|-----|-----|-------------------------------------------------| | audioFormat | number | 是 | 否 | 采样格式,参见 ohos.multimedia.audio.AudioSampleFormat | -| channelCount | number | 是 | 否 | 通道数,参加 ohos.multimedia.audio.AudioChannel | -| sampleRate | number | 是 | 否 | 采样率,参加 ohos.multimedia.audio.AudioSamplingRate | +| channelCount | number | 是 | 否 | 通道数,参见 ohos.multimedia.audio.AudioChannel | +| sampleRate | number | 是 | 否 | 采样率,参见 ohos.multimedia.audio.AudioSamplingRate | | data | ArrayBuffer | 否 | 是 | 采样数据 | ## AudioDeviceModuleOptions @@ -2904,6 +2904,75 @@ let nativeVideoRenderer = new webrtc.NativeVideoRenderer(); nativeVideoRenderer.setVideoTrack(this.localVideoTrack); ``` +### setMirror + +setMirror(mirrorHorizontally: boolean): void + +设置视频流是否水平镜像显示,默认为false。 + +#### 参数 + +| 参数名 | 类型 | 必填 | 说明 | +|-----------|--------|----|----------------------------------------------------------------------------------------------| +| mirrorHorizontally | boolean | 是 | 如果为true,在水平方向镜像显示视频流。 | + +#### 返回值 + +无 + +#### 示例 + +```typescript +let nativeVideoRenderer = new webrtc.NativeVideoRenderer(); +nativeVideoRenderer.setMirror(true); +``` + +### setMirrorVertically + +setMirrorVertically(mirrorVertically: boolean): void + +设置视频流是否垂直镜像显示,默认为false。 + +#### 参数 + +| 参数名 | 类型 | 必填 | 说明 | +|-----------|--------|----|----------------------------------------------------------------------------------------------| +| mirrorVertically | boolean | 是 | 如果为true,在垂直方向镜像显示视频流。 | + +#### 返回值 + +无 + +#### 示例 + +```typescript +let nativeVideoRenderer = new webrtc.NativeVideoRenderer(); +nativeVideoRenderer.setMirrorVertically(true); +``` + +### setScalingMode + +setScalingMode(mode: number): void + +设置视频流显示的缩放模式,默认为0,即缩放内容以适应窗口的大小。 + +#### 参数 + +| 参数名 | 类型 | 必填 | 说明 | +|-----------|--------|----|----------------------------------------------------------------------------------------------| +| mode | number | 是 | 缩放模式,参见 [ScalingMode](#scalingmode) 。 | + +#### 返回值 + +无 + +#### 示例 + +```typescript +let nativeVideoRenderer = new webrtc.NativeVideoRenderer(); +nativeVideoRenderer.setScalingMode(1); +``` + ### release release(): void @@ -2964,3 +3033,124 @@ build() this.mXComponentController.setVideoTrack(this.localVideoTrack); ``` + +### setMirror + +setMirror(mirrorHorizontally: boolean): void + +设置视频流是否应该水平镜像显示,默认为false。 + +#### 参数 + +| 参数名 | 类型 | 必填 | 说明 | +|-----------|--------|----|----------------------------------------------------------------------------------------------| +| mirrorHorizontally | boolean | 是 | 如果为true,在水平方向镜像显示视频流。 | + +#### 返回值 + +无 + +#### 示例 + +```typescript +// 初始化 XComponent 控制器 +mXComponentController: VideoRenderController = new VideoRenderController(); + +build() +{ + // ...... + // 声明 XComponent 组件,并指定 XComponent 控制器 + XComponent({ + id: "local-video", + type: XComponentType.SURFACE, + controller: this.mXComponentController + }) + // ...... +} + +this.mXComponentController.setMirror(true); +``` + +### setMirrorVertically + +setMirrorVertically(mirrorVertically: boolean): void + +设置视频流是否应该垂直镜像显示,默认为false。 + +#### 参数 + +| 参数名 | 类型 | 必填 | 说明 | +|-----------|--------|----|----------------------------------------------------------------------------------------------| +| mirrorVertically | boolean | 是 | 如果为true,在垂直方向镜像显示视频流。 | + +#### 返回值 + +无 + +#### 示例 + +```typescript +// 初始化 XComponent 控制器 +mXComponentController: VideoRenderController = new VideoRenderController(); + +build() +{ + // ...... + // 声明 XComponent 组件,并指定 XComponent 控制器 + XComponent({ + id: "local-video", + type: XComponentType.SURFACE, + controller: this.mXComponentController + }) + // ...... +} + +this.mXComponentController.setMirrorVertically(true); +``` + +### setScalingMode + +setScalingMode(mode: ScalingMode): void + +设置视频流显示的缩放模式,默认为 ScalingMode.Fill,即缩放内容以适应窗口的大小。 + +#### 参数 + +| 参数名 | 类型 | 必填 | 说明 | +|-----------|--------|----|----------------------------------------------------------------------------------------------| +| mode | [ScalingMode](#scalingmode) | 是 | 缩放模式,参见 ScalingMode 。 | + +#### 返回值 + +无 + +#### 示例 + +```typescript +// 初始化 XComponent 控制器 +mXComponentController: VideoRenderController = new VideoRenderController(); + +build() +{ + // ...... + // 声明 XComponent 组件,并指定 XComponent 控制器 + XComponent({ + id: "local-video", + type: XComponentType.SURFACE, + controller: this.mXComponentController + }) + // ...... +} + +this.mXComponentController.setScalingMode(ScalingMode.Fill); +``` + +## ScalingMode + +缩放模式枚举。 + +| 名称 | 值 | 说明 | +|---------|-----|--------------------------------------| +| Fill | 0 | 缩放内容以适应窗口的大小,如果需要可以改变内容的宽高比。 | +| AspectFill | 1 | 缩放内容以填充窗口的大小。保持宽高比不变,部分内容可能会被裁剪。 | +| AspectFit | 2 | 缩放内容以适应窗口的大小。保持宽高比不变,窗口左右或上下可能会有黑边。 | diff --git a/sdk/ohos/har_hap/entry/src/main/ets/pages/Index.ets b/sdk/ohos/har_hap/entry/src/main/ets/pages/Index.ets index b4afc89c78433713fc2e2e8950708c4f5cf92f19..9d2100140a009b8ce0a2ce30dd0e6911fd8d5deb 100644 --- a/sdk/ohos/har_hap/entry/src/main/ets/pages/Index.ets +++ b/sdk/ohos/har_hap/entry/src/main/ets/pages/Index.ets @@ -13,7 +13,7 @@ * limitations under the License. */ -import webrtc, { Logging, LoggingSeverity, VideoRenderController } from 'ohos_webrtc'; +import webrtc, { Logging, LoggingSeverity, VideoRenderController, ScalingMode } from 'ohos_webrtc'; import abilityAccessCtrl, { PermissionRequestResult } from '@ohos.abilityAccessCtrl'; import webSocket from '@ohos.net.webSocket'; import promptAction from '@ohos.promptAction'; @@ -100,8 +100,8 @@ struct Index { Row() { TextInput({ placeholder: '请输入对端ID' }) - .width('300px') - .height('54px') + .width(200) + .height(54) .fontSize(28) .fontWeight(FontWeight.Normal) .type(InputType.Number) @@ -111,9 +111,9 @@ struct Index { }) Button(this.buttonTitle) - .width('240px') - .height('54px') - .fontSize(28) + .width(150) + .height(54) + .fontSize(20) .fontWeight(FontWeight.Bold) .margin({ top: 20 }) .onClick(() => { @@ -131,7 +131,7 @@ struct Index { this.sendMessage('SESSION ' + this.peerId); this.buttonTitle = 'Disconnect'; }) - .margin({ left: 24, right: 24 }) + .margin({ left: 10, right: 20 }) Row() { Checkbox({ name: 'remote_offerer', group: 'checkboxGroup' }) @@ -159,7 +159,6 @@ struct Index { }) .width('640px') .height('480px') - .padding({right: 10}) .onLoad((context?) => { console.log(TAG, "context: " + context); console.log(TAG, "surfaceId: " + this.mXComponentController1.getXComponentSurfaceId()); @@ -376,6 +375,9 @@ struct Index { if (this.localVideoTrack) { this.mXComponentController1.setVideoTrack(this.localVideoTrack); } + + this.mXComponentController1.setMirror(true); + this.mXComponentController1.setScalingMode(ScalingMode.AspectFit); } } diff --git a/sdk/ohos/har_hap/ohos_webrtc/Index.ets b/sdk/ohos/har_hap/ohos_webrtc/Index.ets index 21ce64cd67a14f94b89365240df7437f0f424c25..3e02a899ab488eca6c57df4ccbccb582c154c7bf 100644 --- a/sdk/ohos/har_hap/ohos_webrtc/Index.ets +++ b/sdk/ohos/har_hap/ohos_webrtc/Index.ets @@ -18,4 +18,4 @@ import webrtc from 'libohos_webrtc.so' export default webrtc; export { Logging, LoggingSeverity } from './src/main/ets/log/Logging'; -export { VideoRenderController } from './src/main/ets/xcomponent/VideoRenderController'; +export { VideoRenderController, ScalingMode } from './src/main/ets/xcomponent/VideoRenderController'; diff --git a/sdk/ohos/har_hap/ohos_webrtc/src/main/ets/xcomponent/VideoRenderController.ets b/sdk/ohos/har_hap/ohos_webrtc/src/main/ets/xcomponent/VideoRenderController.ets index 03bdd02a7b75a65094998dcd9c395fb768d3872b..22e740289f4764ad0771dd2b5cdbffed6d4c8893 100644 --- a/sdk/ohos/har_hap/ohos_webrtc/src/main/ets/xcomponent/VideoRenderController.ets +++ b/sdk/ohos/har_hap/ohos_webrtc/src/main/ets/xcomponent/VideoRenderController.ets @@ -18,6 +18,8 @@ import { Logging } from '../log/Logging' const TAG: string = '[XComponentController1]'; +export enum ScalingMode { Fill, AspectFill, AspectFit } + export class VideoRenderController extends XComponentController { private renderer: NativeVideoRenderer = new NativeVideoRenderer(); @@ -25,6 +27,18 @@ export class VideoRenderController extends XComponentController { this.renderer.setVideoTrack(track); } + setMirror(mirror: boolean) : void { + this.renderer.setMirror(mirror); + } + + setMirrorVertically(mirrorVertically: boolean): void { + this.renderer.setMirrorVertically(mirrorVertically); + } + + setScalingMode(mode: ScalingMode) : void { + this.renderer.setScalingMode(mode); + } + onSurfaceCreated(surfaceId: string): void { Logging.d(TAG, 'onSurfaceCreated surfaceId: ' + surfaceId); this.renderer.init(surfaceId); diff --git a/sdk/ohos/har_hap/ohos_webrtc/src/main/libohos_webrtc/webrtc.d.ts b/sdk/ohos/har_hap/ohos_webrtc/src/main/libohos_webrtc/webrtc.d.ts index 309f4910bde5797c311e8d372d8e934c96a6dd85..0e54bef2c022420124e6c1aac979033e5584d3f5 100644 --- a/sdk/ohos/har_hap/ohos_webrtc/src/main/libohos_webrtc/webrtc.d.ts +++ b/sdk/ohos/har_hap/ohos_webrtc/src/main/libohos_webrtc/webrtc.d.ts @@ -824,8 +824,6 @@ export interface DeviceChangeEvent extends Event { // https://www.w3.org/TR/mediacapture-streams/#mediadevices export interface MediaDevices extends EventTarget { - ondevicechange: (this: MediaDevices, event: DeviceChangeEvent) => void | null; - enumerateDevices(): Promise; getSupportedConstraints(): MediaTrackSupportedConstraints; getUserMedia(constraints?: MediaStreamConstraints): Promise; @@ -843,6 +841,9 @@ export interface NativeVideoRenderer { init(surfaceId: string): void; setVideoTrack(videoTrack: MediaStreamTrack | null): void; + setMirror(mirrorHorizontally: boolean): void; + setMirrorVertically(mirrorVertically: boolean): void; + setScalingMode(mode: number): void; release(): void; } diff --git a/sdk/ohos/src/ohos_webrtc/render/native_video_renderer.cpp b/sdk/ohos/src/ohos_webrtc/render/native_video_renderer.cpp index ffa61a8f47f93866e61982f81711cf90d1e44d00..2ba739e5e5ec19570f7d349d421588216d0f7a78 100644 --- a/sdk/ohos/src/ohos_webrtc/render/native_video_renderer.cpp +++ b/sdk/ohos/src/ohos_webrtc/render/native_video_renderer.cpp @@ -39,6 +39,9 @@ void NapiNativeVideoRenderer::Init(Napi::Env env, Napi::Object exports) InstanceAccessor<&NapiNativeVideoRenderer::GetSharedContext>(kAttributeNameSharedContext), InstanceAccessor<&NapiNativeVideoRenderer::GetVideoTrack>(kAttributeNameVideoTrack), InstanceMethod<&NapiNativeVideoRenderer::SetVideoTrack>(kMethodNameSetVideoTrack), + InstanceMethod<&NapiNativeVideoRenderer::SetMirror>(kMethodNameSetMirror), + InstanceMethod<&NapiNativeVideoRenderer::SetMirrorVertically>(kMethodNameSetMirrorVertically), + InstanceMethod<&NapiNativeVideoRenderer::SetScalingMode>(kMethodNameSetScalingMode), InstanceMethod<&NapiNativeVideoRenderer::Init>(kMethodNameInit), InstanceMethod<&NapiNativeVideoRenderer::Release>(kMethodNameRelease), InstanceMethod<&NapiNativeVideoRenderer::ToJson>(kMethodNameToJson), @@ -171,6 +174,64 @@ Napi::Value NapiNativeVideoRenderer::Release(const Napi::CallbackInfo& info) return info.Env().Undefined(); } +Napi::Value NapiNativeVideoRenderer::SetMirror(const Napi::CallbackInfo& info) +{ + RTC_LOG(LS_VERBOSE) << __FUNCTION__; + + if (info.Length() < 1) { + NAPI_THROW(Error::New(info.Env(), "Wrong number of arguments"), info.Env().Undefined()); + } + + if (!info[0].IsBoolean()) { + NAPI_THROW(Error::New(info.Env(), "The first argument is not boolean"), info.Env().Undefined()); + } + + if (renderer_) { + renderer_->SetMirrorHorizontally(info[0].As().Value()); + } + + return info.Env().Undefined(); +} + +Napi::Value NapiNativeVideoRenderer::SetMirrorVertically(const Napi::CallbackInfo& info) +{ + RTC_LOG(LS_VERBOSE) << __FUNCTION__; + + if (info.Length() < 1) { + NAPI_THROW(Error::New(info.Env(), "Wrong number of arguments"), info.Env().Undefined()); + } + + if (!info[0].IsBoolean()) { + NAPI_THROW(Error::New(info.Env(), "The first argument is not boolean"), info.Env().Undefined()); + } + + if (renderer_) { + renderer_->SetMirrorVertically(info[0].As().Value()); + } + + return info.Env().Undefined(); +} + +Napi::Value NapiNativeVideoRenderer::SetScalingMode(const Napi::CallbackInfo& info) +{ + RTC_LOG(LS_VERBOSE) << __FUNCTION__; + + if (info.Length() < 1) { + NAPI_THROW(Error::New(info.Env(), "Wrong number of arguments"), info.Env().Undefined()); + } + + if (!info[0].IsNumber()) { + NAPI_THROW(Error::New(info.Env(), "The first argument is not number"), info.Env().Undefined()); + } + + auto mode = info[0].As().Int32Value(); + if (renderer_) { + renderer_->SetScalingMode(static_cast(mode)); + } + + return info.Env().Undefined(); +} + Napi::Value NapiNativeVideoRenderer::ToJson(const Napi::CallbackInfo& info) { RTC_DLOG(LS_VERBOSE) << __FUNCTION__; diff --git a/sdk/ohos/src/ohos_webrtc/render/native_video_renderer.h b/sdk/ohos/src/ohos_webrtc/render/native_video_renderer.h index c211b3b41fdd6144b9d2fa351acfeb81c5e2723b..ccf9408a3c565195952cc2834ef3788285189dd5 100644 --- a/sdk/ohos/src/ohos_webrtc/render/native_video_renderer.h +++ b/sdk/ohos/src/ohos_webrtc/render/native_video_renderer.h @@ -36,6 +36,9 @@ public: NAPI_ATTRIBUTE_NAME_DECLARE(SharedContext, sharedContext); NAPI_METHOD_NAME_DECLARE(Init, init); NAPI_METHOD_NAME_DECLARE(SetVideoTrack, setVideoTrack); + NAPI_METHOD_NAME_DECLARE(SetMirror, setMirror); + NAPI_METHOD_NAME_DECLARE(SetMirrorVertically, setMirrorVertically); + NAPI_METHOD_NAME_DECLARE(SetScalingMode, setScalingMode); NAPI_METHOD_NAME_DECLARE(Release, release); NAPI_METHOD_NAME_DECLARE(ToJson, toJSON); @@ -52,6 +55,9 @@ protected: Napi::Value SetVideoTrack(const Napi::CallbackInfo& info); Napi::Value Init(const Napi::CallbackInfo& info); Napi::Value Release(const Napi::CallbackInfo& info); + Napi::Value SetMirror(const Napi::CallbackInfo& info); + Napi::Value SetMirrorVertically(const Napi::CallbackInfo& info); + Napi::Value SetScalingMode(const Napi::CallbackInfo& info); Napi::Value ToJson(const Napi::CallbackInfo& info); void AddSink(); diff --git a/sdk/ohos/src/ohos_webrtc/render/native_window_renderer.h b/sdk/ohos/src/ohos_webrtc/render/native_window_renderer.h index a547b9c1fa80848059b641b1ef0a97279ecc61a3..0f9efa16d34d1f413016ae07ecc5bafb7414a96c 100644 --- a/sdk/ohos/src/ohos_webrtc/render/native_window_renderer.h +++ b/sdk/ohos/src/ohos_webrtc/render/native_window_renderer.h @@ -26,10 +26,25 @@ namespace adapter { class NativeWindowRenderer : public rtc::VideoSinkInterface { public: + enum class ScalingMode { + // Scale the content to fit the size of the window by changing the aspect ratio of the content if necessary. + FILL = 0, + // Scale the content to fill the size of the window. Some portion of the content may be clipped to fill the + // window’s bounds. + ASPECT_FILL, + // Scale the content to fit the size of the window by maintaining the aspect ratio. Any remaining area of the + // window bounds is blank. + ASPECT_FIT + }; + virtual ~NativeWindowRenderer(); uint64_t GetSurfaceId() const; + virtual void SetMirrorHorizontally(bool mirror) {} + virtual void SetMirrorVertically(bool mirror) {} + virtual void SetScalingMode(ScalingMode scaleMode) {} + protected: explicit NativeWindowRenderer(ohos::NativeWindow window); diff --git a/sdk/ohos/src/ohos_webrtc/render/native_window_renderer_gl.cpp b/sdk/ohos/src/ohos_webrtc/render/native_window_renderer_gl.cpp index dd37c760300e85a8a89e4eb6125a81a9962ce17d..4b4ce352bb9fcbf4dddba36746e0491f82a70aac 100644 --- a/sdk/ohos/src/ohos_webrtc/render/native_window_renderer_gl.cpp +++ b/sdk/ohos/src/ohos_webrtc/render/native_window_renderer_gl.cpp @@ -26,6 +26,26 @@ namespace webrtc { namespace adapter { +namespace { + +int32_t GetRotatedWidth(const VideoFrame& frame) +{ + if (frame.rotation() % kVideoRotation_180 == 0) { + return frame.width(); + } + return frame.height(); +} + +int32_t GetRotatedHeight(const VideoFrame& frame) +{ + if (frame.rotation() % kVideoRotation_180 == 0) { + return frame.height(); + } + return frame.width(); +} + +} // namespace + std::unique_ptr NativeWindowRendererGl::Create(ohos::NativeWindow window, std::shared_ptr sharedContext) { @@ -105,6 +125,27 @@ NativeWindowRendererGl::~NativeWindowRendererGl() thread_->Stop(); } +void NativeWindowRendererGl::SetMirrorHorizontally(bool mirror) +{ + RTC_LOG(LS_VERBOSE) << __FUNCTION__ << " mirror: " << mirror; + + thread_->PostTask([this, mirror] { mirrorHorizontally_ = mirror; }); +} + +void NativeWindowRendererGl::SetMirrorVertically(bool mirror) +{ + RTC_LOG(LS_VERBOSE) << __FUNCTION__ << " mirror: " << mirror; + + thread_->PostTask([this, mirror] { mirrorVertically_ = mirror; }); +} + +void NativeWindowRendererGl::SetScalingMode(ScalingMode scaleMode) +{ + RTC_LOG(LS_VERBOSE) << __FUNCTION__ << " scaleMode: " << scaleMode; + + thread_->PostTask([this, scaleMode] { scaleMode_ = scaleMode; }); +} + void NativeWindowRendererGl::OnFrame(const VideoFrame& frame) { RTC_DLOG(LS_VERBOSE) << __FUNCTION__ << " this=" << this; @@ -116,15 +157,7 @@ void NativeWindowRendererGl::OnFrame(const VideoFrame& frame) return; } - thread_->PostTask([this, frame = frame] { - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - drawMatrix_.Reset(); - videoFrameDrawer_->DrawFrame( - frame, *textureDrawer_, drawMatrix_, 0, 0, eglEnv_->GetSurfaceWidth(), eglEnv_->GetSurfaceHeight()); - eglEnv_->SwapBuffers(); - }); + thread_->PostTask([this, frame = frame] { RenderFrame(frame); }); } void NativeWindowRendererGl::OnDiscardedFrame() @@ -137,5 +170,55 @@ void NativeWindowRendererGl::OnConstraintsChanged(const webrtc::VideoTrackSource RTC_DLOG(LS_VERBOSE) << __FUNCTION__; } +void NativeWindowRendererGl::RenderFrame(const VideoFrame& frame) +{ + int viewportX = 0; + int viewportY = 0; + int viewportWidth = eglEnv_->GetSurfaceWidth(); + int viewportHeight = eglEnv_->GetSurfaceHeight(); + if (viewportWidth <= 0 || viewportHeight <= 0) { + RTC_LOG(LS_WARNING) << "Invalid surface size"; + return; + } + + float drawnAspectRatio = 1.0f * viewportWidth / viewportHeight; + float frameAspectRatio = 1.0f * GetRotatedWidth(frame) / GetRotatedHeight(frame); + switch (scaleMode_) { + case ScalingMode::ASPECT_FILL: { + if (frameAspectRatio > drawnAspectRatio) { + viewportX = (viewportWidth - viewportHeight * frameAspectRatio) / 2.0f; + viewportWidth = viewportHeight * frameAspectRatio; + } else { + viewportY = (viewportHeight - viewportWidth / frameAspectRatio) / 2.0f; + viewportHeight = viewportWidth / frameAspectRatio; + } + break; + } + case ScalingMode::ASPECT_FIT: { + if (frameAspectRatio > drawnAspectRatio) { + viewportY = (viewportHeight - viewportWidth / frameAspectRatio) / 2.0f; + viewportHeight = viewportWidth / frameAspectRatio; + } else { + viewportX = (viewportWidth - viewportHeight * frameAspectRatio) / 2.0f; + viewportWidth = viewportHeight * frameAspectRatio; + } + break; + } + default: + break; + } + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + drawMatrix_.Reset(); + drawMatrix_.PreScale(mirrorHorizontally_ ? -1.0f : 1.0f, mirrorVertically_ ? -1.0f : 1.0f, 0.5f, 0.5f); + RTC_DLOG(LS_VERBOSE) << "Draw matrix: " << drawMatrix_; + + videoFrameDrawer_->DrawFrame( + frame, *textureDrawer_, drawMatrix_, viewportX, viewportY, viewportWidth, viewportHeight); + eglEnv_->SwapBuffers(); +} + } // namespace adapter } // namespace webrtc diff --git a/sdk/ohos/src/ohos_webrtc/render/native_window_renderer_gl.h b/sdk/ohos/src/ohos_webrtc/render/native_window_renderer_gl.h index 167aa7e2bd3b7c5a54e5837e52c4b185aecf56ba..4620522b4d5fc0adb23819dd2cbb2a3ddc984aa3 100644 --- a/sdk/ohos/src/ohos_webrtc/render/native_window_renderer_gl.h +++ b/sdk/ohos/src/ohos_webrtc/render/native_window_renderer_gl.h @@ -40,6 +40,10 @@ public: ~NativeWindowRendererGl() override; + void SetMirrorHorizontally(bool mirror) override; + void SetMirrorVertically(bool mirror) override; + void SetScalingMode(ScalingMode scaleMode) override; + protected: NativeWindowRendererGl( ohos::NativeWindow window, std::shared_ptr sharedContext, const std::string& threadName); @@ -48,6 +52,8 @@ protected: void OnDiscardedFrame() override; void OnConstraintsChanged(const webrtc::VideoTrackSourceConstraints& constraints) override; + void RenderFrame(const VideoFrame& frame); + private: int32_t width_{}; int32_t height_{}; @@ -62,6 +68,10 @@ private: Matrix drawMatrix_; std::unique_ptr textureDrawer_; std::unique_ptr videoFrameDrawer_; + + bool mirrorHorizontally_{false}; + bool mirrorVertically_{false}; + ScalingMode scaleMode_{ScalingMode::FILL}; }; } // namespace adapter diff --git a/sdk/ohos/src/ohos_webrtc/render/video_frame_drawer.cpp b/sdk/ohos/src/ohos_webrtc/render/video_frame_drawer.cpp index c7dac17da2dbd691c0878d40fa9b45808a35175d..6346f575d95427863fd6ed7b93c8c38fec64edce 100644 --- a/sdk/ohos/src/ohos_webrtc/render/video_frame_drawer.cpp +++ b/sdk/ohos/src/ohos_webrtc/render/video_frame_drawer.cpp @@ -40,6 +40,7 @@ void VideoFrameDrawer::DrawFrame( renderMatrix_.Reset(); renderMatrix_.PreRotate(frame.rotation(), 0.5f, 0.5f); renderMatrix_.PreConcat(additionalRenderMatrix); + RTC_DLOG(LS_VERBOSE) << "Render matrix: " << renderMatrix_; if (frame.is_texture()) { auto buffer = static_cast(frame.video_frame_buffer().get()); @@ -104,7 +105,9 @@ void VideoFrameDrawer::DrawTexture( Matrix finalMatrix = buffer->GetTransformMatrix(); finalMatrix.PreConcat(renderMatrix); + RTC_DLOG(LS_VERBOSE) << "Final matrix: " << finalMatrix; auto glFinalMatrix = RenderCommon::ConvertMatrixToGLMatrixData(finalMatrix); + RTC_DLOG(LS_VERBOSE) << "Gl final matrix: " << RenderCommon::DumpGLMatrixDataToString(glFinalMatrix); switch (textureData->GetType()) { case TextureData::Type::OES: