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