gemercheung 3 年之前
父節點
當前提交
c8608cb1ba
共有 2 個文件被更改,包括 248 次插入14 次删除
  1. 74 13
      src/scene/scene.service.ts
  2. 174 1
      src/scene/stream/stream.service.ts

文件差異過大導致無法顯示
+ 74 - 13
src/scene/scene.service.ts


+ 174 - 1
src/scene/stream/stream.service.ts

@@ -1,13 +1,186 @@
 import { Injectable } from '@nestjs/common';
 import { DataChannel } from 'node-datachannel';
-
+import * as path from 'path';
+import { readFileSync } from 'fs';
+import * as streamBuffers from 'stream-buffers';
 @Injectable()
 export class StreamService {
   private channel: DataChannel;
+  private readonly chunk_size = 16000;
+  private readonly block = 36;
 
   setChannel(channel: DataChannel) {
     this.channel = channel;
   }
+  closeChannel() {
+    this.channel = null;
+  }
+
+  pushNormalDataToStream(data: any) {
+    const replyBin = JSON.stringify(data).replace(/\s/g, '');
+    const buff = Buffer.from(replyBin, 'utf-8');
+    if (this.channel && this.channel.isOpen()) {
+      this.channel.sendMessageBinary(buff);
+    }
+  }
 
   pushFrameToSteam(stream: StreamFrameType) {}
+
+  pushTheFirstFrame() {
+    const chunk_size = 16000;
+    const block = 36;
+    console.log('首屏--数据');
+    const paths = path.join(__dirname, '../ws/video');
+    // const clipPath = paths + `/1.v2.h264`;
+    const testClipPath = paths + `/2.h264`;
+    const metaData = {
+      traceIds: [],
+      vehicle: null,
+      newUserStates: [
+        {
+          userId: '1e3fa84d5c29a',
+          playerState: {
+            roomTypeId: '',
+            person: 0,
+            avatarId: 'KGe_Boy',
+            skinId: '10089',
+            roomId: '',
+            isHost: false,
+            isFollowHost: false,
+            skinDataVersion: '1008900008',
+            avatarComponents: '',
+            nickName: '1e3fa84d5c29a',
+            movingMode: 0,
+            attitude: 'walk',
+            areaName: 'LQC',
+            pathName: 'thirdwalk',
+            pathId: 'thirdwalk',
+            avatarSize: 1,
+            extra: '{"removeWhenDisconnected":true}',
+            prioritySync: false,
+            player: {
+              position: { x: -755, y: -1450, z: -34 },
+              angle: { pitch: 0, yaw: 0, roll: 0 },
+            },
+            camera: {
+              position: { x: -1075, y: -1450, z: 86 },
+              angle: { pitch: 0, yaw: 0, roll: 0 },
+            },
+            cameraCenter: null,
+          },
+          renderInfo: {
+            renderType: 0,
+            videoFrame: null,
+            cameraStateType: 0,
+            isMoving: 0,
+            needIfr: 0,
+            isVideo: 0,
+            stillFrame: 0,
+            isRotating: 0,
+            isFollowing: 0,
+            clientPanoTitlesBitmap: [],
+            clientPanoTreceId: '',
+            prefetchVideoId: '',
+            noMedia: false,
+          },
+          event: {
+            id: '',
+            type: 0,
+            points: [],
+            rotateEvent: null,
+            removeVisitorEvent: null,
+          },
+          relation: 1,
+        },
+      ],
+      actionResponses: [],
+      getStateType: 0,
+      code: 0,
+      msg: 'OK',
+    };
+    const metaDataString = JSON.stringify(metaData).replace(/\s/g, '');
+
+    const coordBuff = Buffer.from(metaDataString, 'utf-8');
+
+    console.warn('coordBuff', coordBuff.byteLength);
+
+    // const steamStat = statSync(clipPath);
+
+    // const steamTotalSize = metaData.length + steamStat.size;
+    const clipBuffer = readFileSync(testClipPath);
+    // console.log('clipBuffer', clipBuffer);
+    // const fullBufferList = Buffer.concat([coordBuff, clipBuffer]);
+
+    // const steam = createReadStream(clipPath, {
+    //   highWaterMark: chunk_size - block,
+    // });
+
+    // console.log('fullBufferList', fullBufferList);
+
+    // const steam1 = createReadStream(fullBufferList.toString(), {
+    //   highWaterMark: chunk_size - block,
+    // });
+    const steam = new streamBuffers.ReadableStreamBuffer({
+      frequency: 1, // in milliseconds.
+      chunkSize: chunk_size - block, // in bytes.
+    });
+    steam.put(coordBuff);
+    steam.put(clipBuffer);
+
+    let steamByteLength = 0;
+
+    steam.on('data', (data: Buffer) => {
+      // console.log('data', data, data.byteLength);
+      // console.log('data-size', data);
+      const blockBuffStart = Buffer.alloc(block);
+
+      const packBuffer = Buffer.concat([blockBuffStart, data]);
+
+      // const isLastFrame = packBuffer.byteLength - chunk_size < 0;
+      // console.log('packBuffer', packBuffer.byteLength);
+      // if (isLastFrame) {
+      //   // last frame
+      //   packBuffer = Buffer.concat([packBuffer, coordBuff]);
+      //   console.log('last frame', packBuffer.byteLength);
+      // }
+
+      const framePack = new DataView(
+        packBuffer.buffer.slice(
+          packBuffer.byteOffset,
+          packBuffer.byteOffset + packBuffer.byteLength,
+        ),
+      );
+
+      // 16 bit slot
+      // framePack.setUint32(4)
+      framePack.setUint16(6, block);
+      framePack.setUint16(8, 1); // first render cnt
+      framePack.setUint16(10, 1); // isDIR
+      framePack.setUint16(24, 0);
+      framePack.setUint16(26, 0);
+
+      // 32 bit slot
+      // statusPack.setUint32(12, buff.byteLength);
+      // console.log('metaLen', coordBuff.byteLength);
+      // console.log('metaLen', clipBuffer.byteLength);
+
+      framePack.setUint32(0, 1437227610);
+      framePack.setUint32(12, coordBuff.byteLength); // metaLen
+      framePack.setUint32(16, clipBuffer.byteLength); // mediaLen
+      framePack.setUint32(20, 754871824); //server_time
+      framePack.setUint32(24, 0);
+      framePack.setUint32(28, 0);
+      framePack.setUint32(block - 4, steamByteLength);
+
+      // console.log('statusPack', statusPack);
+      if (this.channel && this.channel.isOpen()) {
+        this.channel.sendMessageBinary(Buffer.from(framePack.buffer));
+      }
+      steamByteLength += data.byteLength;
+    });
+    steam.on('end', () => {
+      steamByteLength = 0;
+      // this.onSteaming = false;
+    });
+  }
 }