Add feature that producer prefer layer and pause or resume according it's consumers

This commit is contained in:
bianxg 2023-04-08 16:06:00 +08:00
parent 30d08b5f91
commit ca32426988
2 changed files with 184 additions and 11 deletions

View file

@ -1298,7 +1298,7 @@ export default class RoomClient
{
if (spotlights.includes(consumer.appData.peerId))
{
await this._resumeConsumer(consumer);
await this._startConsumer(consumer);
}
else
{
@ -1762,27 +1762,37 @@ export default class RoomClient
{
videoGoogleStartBitrate : 1000
},
appData :
stopTracks : false,
disableTrackOnPause : false,
zeroRtpOnPause : true,
appData :
{
source : 'webcam',
width,
height,
resolutionScalings
resolutionScalings,
pasued : false
}
});
this._webcamProducer.pause();
}
else
{
this._webcamProducer = await this._sendTransport.produce({
track,
encodings : [ { networkPriority } ],
appData :
encodings : [ { networkPriority } ],
stopTracks : false,
disableTrackOnPause : false,
zeroRtpOnPause : true,
appData :
{
source : 'webcam',
width,
height
height,
pasued : false
}
});
this._webcamProducer.pause();
}
store.dispatch(producerActions.addProducer(
@ -2219,7 +2229,7 @@ export default class RoomClient
if (mute)
await this._pauseConsumer(consumer);
else
await this._resumeConsumer(consumer);
await this._startConsumer(consumer);
}
}
}
@ -2323,7 +2333,11 @@ export default class RoomClient
async _startConsumer(consumer)
{
return this._resumeConsumer(consumer, { initial: true });
const firstTimeStart = consumer.appData.firstTimeStart;
consumer.appData.firstTimeStart = false;
return this._resumeConsumer(consumer, { initial: firstTimeStart });
}
async lowerPeerHand(peerId)
@ -2389,6 +2403,26 @@ export default class RoomClient
}
}
async pauseVideoSend(paused)
{
logger.debug('pauseVideoSend() [pasued:"%s"]', paused.toString());
try
{
if (this._webcamProducer)
{
if (paused)
await this._webcamProducer.pause();
else
await this._webcamProducer.resume();
}
}
catch (error)
{
logger.error('pauseVideoSend() [error:"%o"]', error);
}
}
async setConsumerPreferredLayers(consumerId, spatialLayer, temporalLayer)
{
logger.debug(
@ -2808,6 +2842,25 @@ export default class RoomClient
switch (notification.method)
{
case 'producerPauseReq':
{
this.pauseVideoSend(true);
break;
}
case 'producerResumeReq':
{
this.pauseVideoSend(false);
break;
}
case 'maxSendingSpatialLayer':
{
const { spatialLayer } = notification.data;
this.setMaxSendingSpatialLayer(spatialLayer);
break;
}
case 'enteredLobby':
{
store.dispatch(roomActions.setInLobby(true));
@ -3339,7 +3392,12 @@ export default class RoomClient
producerId,
kind,
rtpParameters,
appData : { ...appData, peerId } // Trick.
appData :
{
...appData,
peerId,
firstTimeStart : true
} // Trick.
});
if (this._recvTransport.appData.encodedInsertableStreams)
@ -3392,7 +3450,13 @@ export default class RoomClient
store.dispatch(consumerActions.addConsumer(consumerStoreObject, peerId));
await this._startConsumer(consumer);
if (kind === 'video')
{
if (this._spotlights.peerInSpotlights(peerId))
await this._startConsumer(consumer);
}
else
await this._startConsumer(consumer);
if (kind === 'audio')
{

View file

@ -567,6 +567,55 @@ class Room extends EventEmitter
});
}
_calcProducerPreferredLayer(peer, producer, reason)
{
let producerPaused = true;
let producerPreferredLayer = 0;
logger.debug(
'_calcProducerPreferredLayer as %s[room:"%s", peer:"%s", producer:"%s" paused:"%s", layer: %d]',
reason, this._roomId, peer.id,
producer.id, producer.appData.paused,
producer.appData.preferredLayer);
for (const consumerId of producer.appData.consumersPauseState.keys())
{
const paused = producer.appData.consumersPauseState.get(consumerId);
const preferredLayer = producer.appData.consumersPreferredLayer.get(consumerId);
logger.debug('consumer" %s paused:%s preferredLayer: %d',
consumerId, paused, preferredLayer);
if (!paused)
producerPaused = false;
if (preferredLayer > producerPreferredLayer)
producerPreferredLayer = preferredLayer;
}
if (producerPaused !== producer.appData.paused)
{
logger.debug('producer pause: %s', producerPaused);
if (producerPaused)
{
this._notification(peer.socket, 'producerPauseReq');
}
else
{
this._notification(peer.socket, 'producerResumeReq');
}
producer.appData.paused = producerPaused;
}
if (producerPreferredLayer !== producer.appData.preferredLayer)
{
logger.debug('producer preferLayer: %d', producerPreferredLayer);
this._notification(peer.socket, 'maxSendingSpatialLayer', {
peerId : peer.id,
spatialLayer : producerPreferredLayer });
producer.appData.preferredLayer = producerPreferredLayer;
}
}
logStatus()
{
logger.info(
@ -1101,6 +1150,20 @@ class Room extends EventEmitter
// the 'loudest' event of the audioLevelObserver.
appData = { ...appData, peerId: peer.id };
if (kind === 'video' && rtpParameters.encodings.length > 1)
{
const consumersPauseState = new Map();
const consumersPreferredLayer = new Map();
appData = {
...appData,
consumersPauseState : consumersPauseState,
consumersPreferredLayer : consumersPreferredLayer,
paused : true,
preferredLayer : rtpParameters.encodings.length - 1
};
}
let producer = null;
try
@ -1250,6 +1313,15 @@ class Room extends EventEmitter
await consumer.pause();
if (consumer.kind === 'video' && consumer.type !== 'simple')
{
const producerPeer = this._peers[consumer.appData.producerPeerId];
const producer = producerPeer.getProducer(consumer.producerId);
producer.appData.consumersPauseState.set(consumer.id, true);
this._calcProducerPreferredLayer(producerPeer, producer, 'consumer paused');
}
cb();
break;
@ -1269,6 +1341,15 @@ class Room extends EventEmitter
await consumer.resume();
if (consumer.kind === 'video' && consumer.type !== 'simple')
{
const producerPeer = this._peers[consumer.appData.producerPeerId];
const producer = producerPeer.getProducer(consumer.producerId);
producer.appData.consumersPauseState.set(consumer.id, false);
this._calcProducerPreferredLayer(producerPeer, producer, 'consumer resumed');
}
cb();
break;
@ -1288,6 +1369,15 @@ class Room extends EventEmitter
await consumer.setPreferredLayers({ spatialLayer, temporalLayer });
if (consumer.kind === 'video')
{
const producerPeer = this._peers[consumer.appData.producerPeerId];
const producer = producerPeer.getProducer(consumer.producerId);
producer.appData.consumersPreferredLayer.set(consumer.id, spatialLayer);
this._calcProducerPreferredLayer(producerPeer, producer, `consumer prefer layer changed ${spatialLayer}`);
}
cb();
break;
@ -1922,11 +2012,20 @@ class Room extends EventEmitter
{
producerId : producer.id,
rtpCapabilities : consumerPeer.rtpCapabilities,
paused : producer.kind === 'video'
paused : producer.kind === 'video',
appData : { producerPeerId: producerPeer.id }
});
if (producer.kind === 'audio')
await consumer.setPriority(255);
if (producer.kind === 'video' && producer.type !== 'simple')
{
producer.appData.consumersPauseState.set(consumer.id, true);
producer.appData.consumersPreferredLayer.set(consumer.id,
consumer.preferredLayers.spatialLayer);
this._calcProducerPreferredLayer(producerPeer, producer, 'new consumer');
}
}
catch (error)
{
@ -1944,6 +2043,16 @@ class Room extends EventEmitter
// Remove from its map.
consumerPeer.removeConsumer(consumer.id);
if (consumer.kind === 'video' && consumer.type !== 'simple')
{
// const producerPeer = this._peers[consumer.appData.producerPeerId];
// const producer = producerPeer.getProducer(consumer.producerId);
producer.appData.consumersPauseState.delete(consumer.id);
producer.appData.consumersPreferredLayer.delete(consumer.id);
this._calcProducerPreferredLayer(producerPeer, producer, 'consumer removed');
}
this._notification(consumerPeer.socket, 'consumerClosed', { consumerId: consumer.id });
});