This commit is contained in:
lunaticbum 2026-03-29 09:18:56 +09:00
parent a5c0bd67a8
commit e056e68808
4 changed files with 83 additions and 12 deletions

View File

@ -227,7 +227,7 @@ bool MediaAsset::loadVideoWithFFmpeg(int fd) {
}
width_ = codecCtx_->width;
height_ = codecCtx_->height;
swsCtx_ = sws_getContext(width_, height_, codecCtx_->pix_fmt, width_, height_, AV_PIX_FMT_RGBA, SWS_BILINEAR, nullptr, nullptr, nullptr);
swsCtx_ = sws_getContext(width_, height_, codecCtx_->pix_fmt, width_, height_, AV_PIX_FMT_BGRA, SWS_BILINEAR, nullptr, nullptr, nullptr);
if (!swsCtx_) {
LOGE("Could not create SwsContext");
release(); return false;
@ -265,7 +265,7 @@ bool MediaAsset::loadVideoWithFFmpeg(const std::string& path) {
frame_ = av_frame_alloc(); packet_ = av_packet_alloc();
if (!frame_ || !packet_) { release(); return false; }
width_ = codecCtx_->width; height_ = codecCtx_->height;
swsCtx_ = sws_getContext(width_, height_, codecCtx_->pix_fmt, width_, height_, AV_PIX_FMT_RGBA, SWS_BILINEAR, nullptr, nullptr, nullptr);
swsCtx_ = sws_getContext(width_, height_, codecCtx_->pix_fmt, width_, height_, AV_PIX_FMT_BGRA, SWS_BILINEAR, nullptr, nullptr, nullptr);
if (!swsCtx_) { release(); return false; }
rgbBuffer_.resize(width_ * height_ * 4);
LOGI("Successfully loaded video from path: %s", path.c_str());

View File

@ -252,7 +252,7 @@ void Renderer::renderFrame(ANativeWindow* window) {
currentFrameDelay_ = std::chrono::milliseconds(static_cast<long long>(1000.0 / currentMedia_.getFps()));
LOGI("Media type: Video. Frame delay set to %lldms for %.2f FPS", currentFrameDelay_.count(), currentMedia_.getFps());
} else {
currentFrameDelay_ = std::chrono::milliseconds(33); // 이미지일 경우 30fps
currentFrameDelay_ = std::chrono::milliseconds(70); // 이미지일 경우 30fps
LOGI("Media type: Image. Frame delay set to 33ms (~30 FPS)");
}
currentState_ = RenderState::ANIMATING;

View File

@ -93,7 +93,7 @@ Java_bums_lunatic_launcher_wall_NativeRenderer_nativeStartRenderLoop(JNIEnv* env
LOGE("Could not get ANativeWindow from Surface.");
return;
}
ANativeWindow_setBuffersGeometry(window, 0, 0, WINDOW_FORMAT_RGBA_8888);
ANativeWindow_setBuffersGeometry(window, 0, 0, WINDOW_FORMAT_RGBX_8888);
renderer->startRenderLoop(window);
ANativeWindow_release(window);
}

View File

@ -1,6 +1,8 @@
package bums.lunatic.launcher.wall
import android.app.WallpaperManager
import android.content.ContentUris
import android.graphics.BitmapFactory
import android.os.Environment
import android.os.Handler
import android.os.HandlerThread
@ -9,6 +11,8 @@ import android.provider.MediaStore
import android.service.wallpaper.WallpaperService
import android.util.Log
import android.view.SurfaceHolder
import androidx.work.ListenableWorker
import bums.lunatic.launcher.utils.Blog
import java.io.File
class MyWallpaperService : WallpaperService() {
@ -26,7 +30,7 @@ class MyWallpaperService : WallpaperService() {
private lateinit var holder: SurfaceHolder
private var wasInPreview = false
private var nativeRenderer: NativeRenderer? = null
private var mediaFiles: List<File> = emptyList()
private var mediaFiles: MutableList<File> = mutableListOf()
private var isVisible = false
private var isSurfaceValid = false
@ -187,7 +191,7 @@ class MyWallpaperService : WallpaperService() {
nativeRenderer?.setTurnPageDuration(8000)
nativeRenderer?.setAnimationMode(NativeRenderer.ANIMATION_MODE_PAN)
nativeRenderer?.setTransitionMode(NativeRenderer.TRANSITION_MODE_FADE)
nativeRenderer?.setAnimationSpeed(2.0f)
nativeRenderer?.setAnimationSpeed(1.0f)
NativeRenderer.nativeSetNextMediaCallback(nextMediaCallback)
@ -198,12 +202,45 @@ class MyWallpaperService : WallpaperService() {
// ... loadMediaFiles, nextMediaCallback, getFdFromPath는 이전과 동일 ...
private fun loadMediaFiles() {
if (!mediaDir.exists()) mediaDir.mkdirs()
mediaFiles = mediaDir.listFiles()
?.filter { supportedExtensions.contains(it.extension.lowercase()) }
?.toList() ?: emptyList()
// mediaFiles = mediaDir.listFiles()
// ?.filter { supportedExtensions.contains(it.extension.lowercase()) }
// ?.toList() ?: emptyList()
Log.d(TAG, "Found ${mediaFiles.size} media files.")
val allFiles = mediaDir.listFiles()
val trashFolder = File(mediaDir, "low_res_backup")
if (!trashFolder.exists()) trashFolder.mkdirs()
val invalidImages = mutableListOf<File>()
val wm = WallpaperManager.getInstance(this@MyWallpaperService)
val minWidth = wm.desiredMinimumWidth
val minHeight = wm.desiredMinimumHeight
val requiredSize = Math.max(minWidth, minHeight).times(0.6)
for (file in allFiles) {
if (file.isFile && (file.extension.equals("jpg", true) ||
file.extension.equals("png", true) ||
file.extension.equals("jpeg", true) ||
file.extension.equals("bmp", true) || // BMP 추가
file.extension.equals("webp", true))) {
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
BitmapFactory.decodeFile(file.absolutePath, options)
Blog.LOGE("requiredSize ${requiredSize} w :${options.outWidth} , h : ${options.outHeight}")
if (options.outWidth >= requiredSize && options.outHeight >= requiredSize) {
mediaFiles.add(file)
} else {
invalidImages.add(file) // 조건 미달
}
}
}
// 2. 부적합 이미지 이동 처리 (Job 밖에서 따로 돌려도 무방)
invalidImages.forEach { file ->
val targetFile = File(trashFolder, file.name)
file.renameTo(targetFile) // 파일 이동
}
if (mediaFiles.isNotEmpty()) {
val initialFile = mediaFiles.random()
Log.d(TAG, "Attempting to load initial random media via preloader: ${initialFile.absolutePath}")
@ -223,9 +260,43 @@ class MyWallpaperService : WallpaperService() {
if (!mediaDir.exists()) mediaDir.mkdirs()
mediaFiles = mediaDir.listFiles()
?.filter { supportedExtensions.contains(it.extension.lowercase()) }
?.toList() ?: emptyList()
// mediaFiles = mediaDir.listFiles()
// ?.filter { supportedExtensions.contains(it.extension.lowercase()) }
// ?.toList() ?: emptyList()
val allFiles = mediaDir.listFiles()
val trashFolder = File(mediaDir, "low_res_backup")
if (!trashFolder.exists()) trashFolder.mkdirs()
// val validImages = mutableListOf<File>()
val invalidImages = mutableListOf<File>()
val wm = WallpaperManager.getInstance(this@MyWallpaperService)
val minWidth = wm.desiredMinimumWidth
val minHeight = wm.desiredMinimumHeight
val requiredSize = Math.max(minWidth, minHeight).times(0.6)
for (file in allFiles) {
if (file.isFile && (file.extension.equals("jpg", true) ||
file.extension.equals("png", true) ||
file.extension.equals("jpeg", true) ||
file.extension.equals("bmp", true) || // BMP 추가
file.extension.equals("webp", true))) {
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
BitmapFactory.decodeFile(file.absolutePath, options)
Blog.LOGE("requiredSize ${requiredSize} w :${options.outWidth} , h : ${options.outHeight}")
if (options.outWidth >= requiredSize && options.outHeight >= requiredSize) {
mediaFiles.add(file)
} else {
invalidImages.add(file) // 조건 미달
}
}
}
// 2. 부적합 이미지 이동 처리 (Job 밖에서 따로 돌려도 무방)
invalidImages.forEach { file ->
val targetFile = File(trashFolder, file.name)
file.renameTo(targetFile) // 파일 이동
}
val nextFile = mediaFiles.random()
Log.d(TAG, "Callback: Preloading next random media: ${nextFile.absolutePath}")