1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15// @ts-nocheck 16import media from '@ohos.multimedia.media' 17import fs from '@ohos.file.fs' 18import Logger from './Logger' 19 20const TAG = 'qlw play' 21 22export class mediaPlay { 23 private avPlay: media.AVPlayer = undefined 24 private surfaceId: number = -1 25 public totalDuration: number 26 private handleVideoPlayback: (isVideoPlayback: boolean) => void = false 27 28 async getFileFd(name) { 29 let filesDir = globalThis.abilityContext.filesDir 30 let path = filesDir + '/' + name 31 let file = fs.openSync(path) 32 return file.fd 33 } 34 35 async getRawfileFd(name) { 36 let file = await globalThis.abilityContext.resourceManager.getRawFd(name) 37 return file.fd 38 } 39 40 getCurrentTime() { 41 return 0 42 } 43 44 seek() { 45 46 } 47 48 async init(surfaceId?) { 49 let fd 50 if (surfaceId) { 51 this.surfaceId = surfaceId 52 fd = await this.getFileFd('test.mp4') 53 } else { 54 fd = await this.getFileFd('test.wav') 55 } 56 Logger.info(TAG, ` fd success : ${fd}`) 57 this.avPlay = await media.createAVPlayer() 58 this.setCallBack(this.avPlay) 59 this.avPlay.url = 'fd://' + fd 60 } 61 62 async initVideo(surfaceId) { 63 this.surfaceId = surfaceId 64 let fd = await this.getRawfileFd('video.mp4') 65 Logger.info(TAG, ` fd success : ${fd}`) 66 this.avPlay = await media.createAVPlayer() 67 this.setCallBack(this.avPlay) 68 this.avPlay.url = 'fd://' + fd 69 } 70 71 async Play() { 72 await this.avPlay.play() 73 } 74 75 setCallBack(AVPlayer) { 76 AVPlayer.on('stateChange', async (state, reason) => { 77 switch (state) { 78 case 'idle': 79 Logger.info(TAG, 'state idle start') 80 break; 81 case 'initialized': 82 Logger.info(TAG + 'state initialized start ') 83 if (this.surfaceId != -1) { 84 AVPlayer.surfaceId = String(this.surfaceId) 85 } 86 await AVPlayer.prepare() 87 Logger.info(TAG, 'state initialized end') 88 break; 89 case 'prepared': 90 Logger.info(TAG, 'state prepared start') 91 await AVPlayer.play() 92 Logger.info(TAG, 'state prepared end') 93 break; 94 case 'playing': 95 Logger.info(TAG, 'state playing callback') 96 break; 97 case 'paused': 98 Logger.info(TAG, 'state paused callback') 99 break; 100 case 'completed': 101 if (this.handleVideoPlayback) { 102 this.handleVideoPlayback(true) 103 } 104 await AVPlayer.stop() 105 await AVPlayer.release() 106 case 'error': 107 Logger.info(TAG, 'state error callback') 108 break; 109 } 110 }) 111 AVPlayer.on('error', (err) => { 112 Logger.info(TAG, `state error callback err:${err},code:${err.code},message:${err.message}}`) 113 }) 114 } 115 116 setVideoPlaybackCallback(callback) { 117 this.handleVideoPlayback = callback 118 } 119 120 async release(){ 121 if (this.avPlay){ 122 await this.avPlay.release() 123 Logger.info(TAG, 'avplay release success') 124 } 125 } 126 127 encodeWAV(sampleRateValue, sampleBitsValue, channelCountValue) { 128 let sampleRate = sampleRateValue; 129 let dataLen = sampleRate * 1000; 130 let sampleBits = sampleBitsValue * 8 + 8 // 采样格式 131 let channelCount = channelCountValue; // 单声道 132 let offset = 0; 133 let buffer = new ArrayBuffer(44); 134 let data = new DataView(buffer); 135 // 资源交换文件标识符 136 this.writeString(data, offset, 'RIFF'); 137 offset += 4; 138 // 下个地址开始到文件尾总字节数,即文件大小-8 139 data.setUint32(offset, 36 + dataLen, true); 140 offset += 4; 141 // WAV文件标志 142 this.writeString(data, offset, 'WAVE'); 143 offset += 4; 144 // 波形格式标志 145 this.writeString(data, offset, 'fmt '); 146 offset += 4; 147 // 过滤字节,一般为 0x10 = 16 148 data.setUint32(offset, 16, true); 149 offset += 4; 150 // 格式类别 (PCM形式采样数据) 151 data.setUint16(offset, 1, true); 152 offset += 2; 153 // 通道数 154 data.setUint16(offset, channelCount, true); 155 offset += 2; 156 // 采样率,每秒样本数,表示每个通道的播放速度 157 data.setUint32(offset, sampleRate, true); 158 offset += 4; 159 // 波形数据传输率 (每秒平均字节数) 单声道×每秒数据位数×每样本数据位/8 160 data.setUint32(offset, channelCount * sampleRate * (sampleBits / 8), true); 161 offset += 4; 162 // 快数据调整数 采样一次占用字节数 单声道×每样本的数据位数/8 163 data.setUint16(offset, channelCount * (sampleBits / 8), true); 164 offset += 2; 165 // 每样本数据位数 166 data.setUint16(offset, sampleBits, true); 167 offset += 2; 168 // 数据标识符 169 this.writeString(data, offset, 'data'); 170 offset += 4; 171 // 采样数据总数,即数据总大小-44 172 data.setUint32(offset, dataLen, true); 173 offset += 4; 174 return data; 175 } 176 177 writeString(data, offset, str) { 178 for (let i = 0; i < str.length; i++) { 179 data.setUint8(offset + i, str.charCodeAt(i)); 180 } 181 } 182} 183 184export default new mediaPlay() 185 186