Intégrez un module de rendu vidéo personnalisé au SDK ARTC pour répondre à des exigences spécifiques en matière de précision des couleurs et de contrôle de la fréquence d'images.
Description de la fonctionnalité
Alibaba Real-Time Communication (ARTC) inclut un module de rendu vidéo intégré, éprouvé sur le marché, qui offre une expérience de lecture vidéo stable et efficace.
Pour les scénarios nécessitant un module de rendu développé en interne ou un contrôle précis de la précision des couleurs et de la fréquence d'images, le SDK ARTC fournit des interfaces flexibles permettant d'intégrer un module de rendu vidéo personnalisé.
Prérequis
Avant de configurer les paramètres vidéo, assurez-vous que les conditions suivantes sont remplies :
Vous avez créé une application ApsaraVideo Real-time Communication avec un compte Alibaba Cloud valide. Pour plus d'informations, consultez Créer une application. Vous devez également obtenir un App ID et une App Key depuis la console Application Management.
Vous avez intégré le SDK ARTC à votre projet et implémenté les fonctionnalités de base de communication audio et vidéo. Pour plus d'informations sur l'intégration du SDK, consultez Télécharger et intégrer le SDK. Pour savoir comment implémenter les appels audio et vidéo, consultez Implémenter un appel audio et vidéo.
Principes techniques
Rendu vidéo distant
Rendu vidéo local basé sur un tampon
Rendu vidéo local basé sur un ID de texture
Implémentation
Implémentation Android
1. Enregistrer un observateur
Commencez par appeler la méthode registerVideoSampleObserver de AliRtcEngine pour enregistrer un observateur de traitement personnalisé. Ensuite, implémentez les méthodes de la classe abstraite AliRtcEngine.AliRtcVideoObserver. Cela vous permet d'appliquer des effets de retouche tout au long du pipeline de traitement AliRtcEngine.
Exemple d'enregistrement de l'AliRtcVideoObserver :
mAliRtcEngine.registerVideoSampleObserver(mAliRtcVideoObserver);
Implémentez l'interface abstraite selon vos besoins. ARTC prend en charge le traitement personnalisé à trois étapes : après la capture vidéo locale, avant l'encodage local et après le décodage vidéo distant.
public enum AliRtcVideoObserPosition{
/*! Captured video data. Corresponds to the onLocalVideoSample callback. */
AliRtcPositionPostCapture(1),
/*! Rendered video data. Corresponds to the onRemoteVideoSample callback. */
AliRtcPositionPreRender(2),
/*! Video data before encoding. Corresponds to the onPreEncodeVideoSample callback. */
AliRtcPositionPreEncoder(4);
}
public static abstract class AliRtcVideoObserver {
// Callback for subscribed local video capture data.
public boolean onLocalVideoSample(AliRtcVideoSourceType sourceType, AliRtcVideoSample videoSample){
// TODO: If retouching and effects are needed during local video capture, process them here.
}
// Callback for subscribed remote video data.
public boolean onRemoteVideoSample(String callId,AliRtcVideoSourceType sourceType, AliRtcVideoSample videoSample){
// TODO: If retouching and effects are needed before displaying the frame pulled from the remote end, process them here.
}
// Callback for local video data before encoding.
public boolean onPreEncodeVideoSample(AliRtcVideoSourceType sourceType, AliRtcVideoSample videoRawData){
// TODO: If retouching and effects are needed before encoding the local video frame, process them here.
}
...
public int onGetObservedFramePosition(){
// TODO: Specify the timing for the callback based on your business needs. Use the AliRtcVideoObserPosition values defined above.
// For example, to perform custom processing before capture and pre-rendering, define the following value.
// return AliRtcVideoObserPosition.AliRtcPositionPostCapture.getValue() | AliRtcVideoObserPosition.AliRtcPositionPreRender.getValue();
}
}
Pour utiliser le Queen SDK, vous devez traiter le flux vidéo dans l'interface correspondante.
Annuler l'enregistrement de l'écouteur
Lorsque le traitement personnalisé n'est plus nécessaire, annulez l'enregistrement de l'écouteur afin de réduire les appels depuis la couche SDK, d'améliorer l'efficacité du traitement et d'éviter les fuites de mémoire.
// TODO: Perform resource release tasks.
mAliRtcEngine.unRegisterVideoSampleObserver()
2. Implémenter le traitement personnalisé
Les interfaces de rappel précédentes peuvent être implémentées en appelant la méthode handleBeautyProcess.
private boolean handleBeautyProcess(AliRtcEngine.AliRtcVideoSample videoSample) {
if (!isAdvanceBeautifyOn) { // Specifies whether to enable retouching.
return false;
}
if (mQueenBeautyImp == null) {
mQueenBeautyImp = new QueenBeautyImp(getContext(), videoSample.glContex);
}
return mQueenBeautyImp.onBeautyProcess(videoSample);
}
QueenBeautyImp est une classe wrapper simple pour QueenBeautyEffector.
Créer un processeur de retouche
Créez le processeur comme suit :
// Add a synchronization lock to prevent multiple creations.
private synchronized void ensureQueenEngine(Context context, long glShareContext) {
if (mQueenBeautyEffector == null) {
try {
QueenConfig queenConfig = new QueenConfig();
bool isNeedCreateNewThread = glShareContext != 0; // Specifies whether to create a separate thread. We recommend that you set this to true for texture mode and false for buffer mode.
bool isNeedCreateNewGLContext = true; // Specifies whether to create a GL context. For texture mode, keep this value consistent with isNeedCreateNewThread. For buffer mode, we recommend that you set this to true.
queenConfig.withNewGlThread = isNeedCreateNewThread;
queenConfig.withContext = isNeedCreateNewGLContext;
queenConfig.shareGlContext = glShareContext;
// queenConfig.enableDebugLog = true; // Debugging feature: Enable logs.
mQueenBeautyEffector = new QueenBeautyEffector(context, queenConfig);
// Advanced retouching debugging features.
// mQueenBeautyEffector.getEngine().enableFacePointDebug(true); // Enable facial landmark debugging.
// mQueenBeautyEffector.getEngine().enableFaceDetectGPUMode(false); // Disable the GPU mode for facial recognition.
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Définir les paramètres de retouche
private void updateQueenEngineParams() {
mQueenBeautyEffector.onUpdateParams(() -> {
QueenEngine queenEngine = mQueenBeautyEffector.getEngine();
// Skin smoothing and sharpening share one switch.
queenEngine.enableBeautyType(BeautyFilterType.kSkinBuffing, true); // Skin smoothing switch.
queenEngine.setBeautyParam(com.aliyun.android.libqueen.models.BeautyParams.kBPSkinBuffing, 0.85f); // Skin smoothing. Valid values: [0,1].
queenEngine.setBeautyParam(com.aliyun.android.libqueen.models.BeautyParams.kBPSkinSharpen, 0.2f); // Sharpening. Valid values: [0,1].
// Skin whitening and rosy cheeks share one switch.
queenEngine.enableBeautyType(BeautyFilterType.kSkinWhiting, true); // Skin whitening switch.
queenEngine.setBeautyParam(BeautyParams.kBPSkinWhitening, 0.5f); // Skin whitening. Valid values: [0,1].
// Eye enlarging and face slimming.
queenEngine.enableBeautyType(BeautyFilterType.kFaceShape, true);
queenEngine.updateFaceShape(FaceShapeType.typeBigEye,1.0f);
queenEngine.updateFaceShape(FaceShapeType.typeCutFace,1.0f);
});
}
Traiter les images
Traitez les données sous forme de texture ou de tampon en fonction du type de données du rappel.
// Add a synchronization lock to prevent mQueenBeautyEffector from being destroyed in a multi-threaded environment.
public synchronized boolean onBeautyProcess(AliRtcEngine.AliRtcVideoSample videoSample) {
// Update retouching parameters.
updateQueenEngineParams();
boolean result = false;
if (videoSample.glContex != 0 && videoSample.textureid > 0) {
// Texture mode.
result = onProcessBeautyTexture(videoSample);
} else {
// Buffer mode.
result = onProcessBeautyBuffer(videoSample);
}
return result;
}
Traiter les rappels de texture :
private boolean onProcessBeautyTexture(AliRtcEngine.AliRtcVideoSample videoSample) {
boolean result = false;
boolean isOesTexture = videoSample.format == AliRtcEngine.AliRtcVideoFormat.AliRtcVideoFormatTextureOES;
// The texture captured by an Android camera is by default a landscape image rotated by 270 degrees. The Queen SDK automatically swaps the width and height.
// However, the width and height in the videoSample callback are already corrected by the ARTC SDK. Therefore, you must manually swap the width and height here.
int w = isOesTexture ? videoSample.height : videoSample.width;
int h = isOesTexture ? videoSample.width : videoSample.height;
int newTextId = mQueenBeautyEffector.onProcessTexture((int)videoSample.textureid, isOesTexture, videoSample.matrix, w, h, 270, 0, 0);
if (newTextId != videoSample.textureid) { // 0 indicates QueenResult.QUEEN_OK.
// Modify the texture ID.
videoSample.textureid = newTextId;
videoSample.format = AliRtcEngine.AliRtcVideoFormat.AliRtcVideoFormatTexture2D;
result = true;
}
return result;
}
Traiter les rappels de tampon :
private boolean onProcessBeautyBuffer(AliRtcEngine.AliRtcVideoSample videoSample) {
boolean result = false;
int queenResult = mQueenBeautyEffector.onProcessDataBuf(videoSample.data, videoSample.data, ImageFormat.I420, videoSample.width, videoSample.height, 0, 0, 0, 0);
if (queenResult == 0) {
result = true;
}
return result;
}
3. Quitter et détruire les ressources
Lorsque vous quittez une réunion ou l'interface d'appel vidéo, détruisez rapidement le moteur de traitement personnalisé.
// Add a synchronization lock to prevent mQueenBeautyEffector from being destroyed in a multi-threaded environment.
public synchronized void release() {
if (mQueenBeautyEffector != null) {
mQueenBeautyEffector.onReleaseEngine();
mQueenBeautyEffector = null;
}
}