From 28cfcbd1343c902dbf6636eb5064d59447c63c72 Mon Sep 17 00:00:00 2001 From: San Date: Thu, 31 Oct 2024 16:52:13 +0800 Subject: [PATCH] Set hardware decoding options for rkmpp when hardware decoding is enabled with no OpenCL on non-HDR file --- server/src/services/media.service.spec.ts | 24 ++++++++++++++++ server/src/services/media.service.ts | 2 +- server/src/utils/media.ts | 35 ++++++++++++++++------- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/server/src/services/media.service.spec.ts b/server/src/services/media.service.spec.ts index 65166f42936a33..90c8fa16d704dc 100644 --- a/server/src/services/media.service.spec.ts +++ b/server/src/services/media.service.spec.ts @@ -2148,6 +2148,30 @@ describe(MediaService.name, () => { ); }); + it('should set hardware decoding options for rkmpp when hardware decoding is enabled with no OpenCL on non-HDR file', async () => { + storageMock.readdir.mockResolvedValue(['renderD128']); + storageMock.stat.mockResolvedValue({ isFile: () => false, isCharacterDevice: () => false } as Stats); + mediaMock.probe.mockResolvedValue(probeStub.noAudioStreams); + systemMock.get.mockResolvedValue({ + ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true, crf: 30, maxBitrate: '0' }, + }); + assetMock.getByIds.mockResolvedValue([assetStub.video]); + await sut.handleVideoConversion({ id: assetStub.video.id }); + expect(mediaMock.transcode).toHaveBeenCalledWith( + '/original/path.ext', + 'upload/encoded-video/user-id/as/se/asset-id.mp4', + expect.objectContaining({ + inputOptions: expect.arrayContaining(['-hwaccel rkmpp', '-hwaccel_output_format drm_prime', '-afbc rga']), + outputOptions: expect.arrayContaining([ + expect.stringContaining( + 'scale_rkrga=-2:720:format=nv12:afbc=1', + ), + ]), + twoPass: false, + }), + ); + }); + it('should use software decoding and tone-mapping if hardware decoding is disabled', async () => { storageMock.readdir.mockResolvedValue(['renderD128']); storageMock.stat.mockResolvedValue({ isFile: () => true, isCharacterDevice: () => true } as Stats); diff --git a/server/src/services/media.service.ts b/server/src/services/media.service.ts index 8393f5dc762829..91dbe7ffbcea9a 100644 --- a/server/src/services/media.service.ts +++ b/server/src/services/media.service.ts @@ -496,7 +496,7 @@ export class MediaService extends BaseService { const maliDeviceStat = await this.storageRepository.stat('/dev/mali0'); this.maliOpenCL = maliIcdStat.isFile() && maliDeviceStat.isCharacterDevice(); } catch { - this.logger.debug('OpenCL not available for transcoding, so RKMPP acceleration will use CPU decoding'); + this.logger.debug('OpenCL not available for transcoding, so RKMPP acceleration will use CPU tonemapping'); this.maliOpenCL = false; } } diff --git a/server/src/utils/media.ts b/server/src/utils/media.ts index 03d57296d83b8e..1c959cbc273751 100644 --- a/server/src/utils/media.ts +++ b/server/src/utils/media.ts @@ -58,9 +58,8 @@ export class BaseConfig implements VideoCodecSWConfig { break; } case TranscodeHWAccel.RKMPP: { - handler = - config.accelDecode && hasMaliOpenCL - ? new RkmppHwDecodeConfig(config, devices) + handler = config.accelDecode + ? new RkmppHwDecodeConfig(config, devices, hasMaliOpenCL) : new RkmppSwDecodeConfig(config, devices); break; } @@ -1004,6 +1003,16 @@ export class RkmppSwDecodeConfig extends BaseHWConfig { } export class RkmppHwDecodeConfig extends RkmppSwDecodeConfig { + protected hasMaliOpenCL: boolean; + constructor( + protected config: SystemConfigFFmpegDto, + devices: string[] = [], + hasMaliOpenCL = false, + ) { + super(config, devices); + this.hasMaliOpenCL = hasMaliOpenCL; + } + getBaseInputOptions() { if (this.devices.length === 0) { throw new Error('No RKMPP device found'); @@ -1014,14 +1023,18 @@ export class RkmppHwDecodeConfig extends RkmppSwDecodeConfig { getFilterOptions(videoStream: VideoStreamInfo) { if (this.shouldToneMap(videoStream)) { - const colors = this.getColors(); - return [ - `scale_rkrga=${this.getScaling(videoStream)}:format=p010:afbc=1`, - 'hwmap=derive_device=opencl:mode=read', - `tonemap_opencl=format=nv12:r=pc:p=${colors.primaries}:t=${colors.transfer}:m=${colors.matrix}:tonemap=${this.config.tonemap}:desat=0`, - 'hwmap=derive_device=rkmpp:mode=write:reverse=1', - 'format=drm_prime', - ]; + if (this.hasMaliOpenCL) { + const colors = this.getColors(); + return [ + `scale_rkrga=${this.getScaling(videoStream)}:format=p010:afbc=1`, + 'hwmap=derive_device=opencl:mode=read', + `tonemap_opencl=format=nv12:r=pc:p=${colors.primaries}:t=${colors.transfer}:m=${colors.matrix}:tonemap=${this.config.tonemap}:desat=0`, + 'hwmap=derive_device=rkmpp:mode=write:reverse=1', + 'format=drm_prime', + ]; + } else { + return super.getFilterOptions(videoStream); + } } else if (this.shouldScale(videoStream)) { return [`scale_rkrga=${this.getScaling(videoStream)}:format=nv12:afbc=1`]; }