Custom RTMP saved accounts, RTMP test server, composition pipeline
- Backend: POST /providers/accounts/custom-rtmp to save reusable RTMP servers - Backend: Encrypt rtmpUrl/streamKey in existing token fields, decrypt on GET - Backend: Skip token revocation on DELETE for CUSTOM_RTMP accounts - Backend: Decrypt CUSTOM_RTMP credentials into destinations on plan create/update - Android: Add rtmpUrl/streamKey to LinkedAccount entity + shared parcelable (Room v6) - Android: Add Custom RTMP dialog in AccountsScreen, auto-fill in plan destination picker - Android: Handle CUSTOM_RTMP accounts in CreatePlanViewModel.loadExistingPlan - Add local RTMP test server (tools/rtmp-server.js) with auto-ffplay on publish - Add composition pipeline native code
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "egl_context.h"
|
||||
|
||||
#include <android/log.h>
|
||||
#include <android/native_window.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define TAG "LckEglContext"
|
||||
@@ -201,9 +202,58 @@ bool EglContext::SwapBuffers() {
|
||||
return eglSwapBuffers(display, surface) == EGL_TRUE;
|
||||
}
|
||||
|
||||
bool EglContext::CreatePreviewSurface(ANativeWindow* window) {
|
||||
if (!window || display == EGL_NO_DISPLAY) return false;
|
||||
|
||||
DestroyPreviewSurface();
|
||||
|
||||
previewSurface = eglCreateWindowSurface(display, config, window, nullptr);
|
||||
if (previewSurface == EGL_NO_SURFACE) {
|
||||
LOGE("eglCreateWindowSurface (preview) failed: 0x%x", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
previewWindow = window;
|
||||
eglQuerySurface(display, previewSurface, EGL_WIDTH, &previewWidth);
|
||||
eglQuerySurface(display, previewSurface, EGL_HEIGHT, &previewHeight);
|
||||
LOGI("Preview surface created: %dx%d", previewWidth, previewHeight);
|
||||
return true;
|
||||
}
|
||||
|
||||
void EglContext::DestroyPreviewSurface() {
|
||||
if (previewSurface != EGL_NO_SURFACE && display != EGL_NO_DISPLAY) {
|
||||
// Make sure preview isn't current before destroying
|
||||
eglMakeCurrent(display, surface, surface, context);
|
||||
eglDestroySurface(display, previewSurface);
|
||||
previewSurface = EGL_NO_SURFACE;
|
||||
LOGI("Preview surface destroyed");
|
||||
}
|
||||
if (previewWindow) {
|
||||
ANativeWindow_release(previewWindow);
|
||||
previewWindow = nullptr;
|
||||
}
|
||||
previewWidth = 0;
|
||||
previewHeight = 0;
|
||||
}
|
||||
|
||||
bool EglContext::MakePreviewCurrent() {
|
||||
if (previewSurface == EGL_NO_SURFACE) return false;
|
||||
return eglMakeCurrent(display, previewSurface, previewSurface, context) == EGL_TRUE;
|
||||
}
|
||||
|
||||
bool EglContext::MakeEncoderCurrent() {
|
||||
return eglMakeCurrent(display, surface, surface, context) == EGL_TRUE;
|
||||
}
|
||||
|
||||
bool EglContext::SwapPreviewBuffers() {
|
||||
if (previewSurface == EGL_NO_SURFACE) return false;
|
||||
return eglSwapBuffers(display, previewSurface) == EGL_TRUE;
|
||||
}
|
||||
|
||||
void EglContext::Release() {
|
||||
if (display != EGL_NO_DISPLAY) {
|
||||
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
DestroyPreviewSurface();
|
||||
if (surface != EGL_NO_SURFACE) {
|
||||
eglDestroySurface(display, surface);
|
||||
surface = EGL_NO_SURFACE;
|
||||
|
||||
Reference in New Issue
Block a user