### Access Media Metadata with MediaInfoBuilder Source: https://context7.com/anilbeesetti/nextlib/llms.txt Example demonstrating how to initialize MediaInfoBuilder and access stream properties from a media file. ```kotlin // Example usage with all data classes val mediaInfo = MediaInfoBuilder() .from("/path/to/movie.mkv") .build() mediaInfo?.let { info -> // Access video properties val resolution = info.videoStream?.let { "${it.frameWidth}x${it.frameHeight}" } // Find English audio track val englishAudio = info.audioStreams.find { it.language == "eng" } // Get all subtitle languages val subtitleLanguages = info.subtitleStreams.mapNotNull { it.language } // Calculate total chapter count val chapterCount = info.chapters.size info.release() } ``` -------------------------------- ### Check FFmpeg Library Availability and Support Source: https://context7.com/anilbeesetti/nextlib/llms.txt Use FfmpegLibrary to verify if the FFmpeg library is loaded, get its version, check support for specific media formats, and determine input buffer padding size. ```kotlin import io.github.anilbeesetti.nextlib.media3ext.ffdecoder.FfmpegLibrary import androidx.media3.common.MimeTypes // Check if FFmpeg library is loaded if (FfmpegLibrary.isAvailable()) { val version = FfmpegLibrary.getVersion() println("FFmpeg version: $version") // Check format support before playback val supportsOpus = FfmpegLibrary.supportsFormat(MimeTypes.AUDIO_OPUS) val supportsHevc = FfmpegLibrary.supportsFormat(MimeTypes.VIDEO_H265) val supportsAc3 = FfmpegLibrary.supportsFormat(MimeTypes.AUDIO_AC3) val supportsTrueHd = FfmpegLibrary.supportsFormat(MimeTypes.AUDIO_TRUEHD) println("Opus support: $supportsOpus") println("HEVC support: $supportsHevc") println("AC3 support: $supportsAc3") println("TrueHD support: $supportsTrueHd") // Get input buffer padding size for decoder configuration val paddingSize = FfmpegLibrary.getInputBufferPaddingSize() println("Input buffer padding: $paddingSize bytes") } // Supported MIME types: // Audio: audio/vorbis, audio/opus, audio/flac, audio/alac, audio/mpeg, // audio/ac3, audio/eac3, audio/true-hd, audio/vnd.dts, audio/3gpp (AMR) // Video: video/avc (H.264), video/hevc, video/x-vnd.on2.vp8, video/x-vnd.on2.vp9 ``` -------------------------------- ### Create ExoPlayer with NextRenderersFactory Source: https://context7.com/anilbeesetti/nextlib/llms.txt Use NextRenderersFactory to enable FFmpeg decoders alongside standard MediaCodec decoders. Set EXTENSION_RENDERER_MODE_PREFER to prioritize FFmpeg. ```kotlin import androidx.media3.exoplayer.ExoPlayer import io.github.anilbeesetti.nextlib.media3ext.ffdecoder.NextRenderersFactory // Create ExoPlayer with FFmpeg decoder support val renderersFactory = NextRenderersFactory(applicationContext) .setExtensionRendererMode(NextRenderersFactory.EXTENSION_RENDERER_MODE_PREFER) val player = ExoPlayer.Builder(applicationContext) .setRenderersFactory(renderersFactory) .build() // Load and play media val mediaItem = MediaItem.fromUri("https://example.com/video.mkv") player.setMediaItem(mediaItem) player.prepare() player.play() // Extension renderer modes: // EXTENSION_RENDERER_MODE_OFF - Don't use FFmpeg decoders // EXTENSION_RENDERER_MODE_ON - Use FFmpeg as fallback when MediaCodec fails // EXTENSION_RENDERER_MODE_PREFER - Prefer FFmpeg over MediaCodec ``` -------------------------------- ### Configure FFmpeg Paths and Includes Source: https://github.com/anilbeesetti/nextlib/blob/main/media3ext/src/main/cpp/CMakeLists.txt Sets variables for the FFmpeg library directory and include paths. These paths are relative to the source directory. ```cmake set(ffmpeg_dir ${CMAKE_SOURCE_DIR}/../../../../ffmpeg/output) set(ffmpeg_libs ${ffmpeg_dir}/lib/${ANDROID_ABI}) include_directories(${ffmpeg_dir}/include/${ANDROID_ABI}) ``` -------------------------------- ### Add Project Library Source: https://github.com/anilbeesetti/nextlib/blob/main/mediainfo/src/main/cpp/CMakeLists.txt Defines the main shared library for the project and lists its source files. Ensure all source files are correctly specified. ```cmake add_library(${CMAKE_PROJECT_NAME} SHARED # List C/C++ source files with relative paths to this CMakeLists.txt. main.cpp mediainfo.cpp utils.cpp frame_loader_context.cpp frame_extractor.cpp media_thumbnail_retriever.cpp) ``` -------------------------------- ### Create ExoPlayer with FFmpegOnlyRenderersFactory Source: https://context7.com/anilbeesetti/nextlib/llms.txt Utilize FFmpegOnlyRenderersFactory for consistent software decoding across all devices by bypassing hardware MediaCodec decoders. ```kotlin import androidx.media3.exoplayer.ExoPlayer import io.github.anilbeesetti.nextlib.media3ext.ffdecoder.FFmpegOnlyRenderersFactory // Create player with software-only decoding val renderersFactory = FFmpegOnlyRenderersFactory(applicationContext) val player = ExoPlayer.Builder(applicationContext) .setRenderersFactory(renderersFactory) .build() // All audio and video will be decoded using FFmpeg val mediaItem = MediaItem.fromUri("/storage/emulated/0/Movies/video.mp4") player.setMediaItem(mediaItem) player.prepare() player.play() ``` -------------------------------- ### Configure FFmpeg Paths Source: https://github.com/anilbeesetti/nextlib/blob/main/mediainfo/src/main/cpp/CMakeLists.txt Sets variables for FFmpeg library and include directories. These paths are relative to the CMakeLists.txt file. ```cmake set(ffmpeg_dir ${CMAKE_SOURCE_DIR}/../../../../ffmpeg/output) set(ffmpeg_libs ${ffmpeg_dir}/lib/${ANDROID_ABI}) ``` -------------------------------- ### Add NextLib Media3 Extensions Dependency (Kotlin DSL) Source: https://github.com/anilbeesetti/nextlib/blob/main/README.md Include this dependency in your app's build.gradle.kts file to add Media3 software decoders and extensions provided by NextLib. ```kotlin dependencies { implementation("io.github.anilbeesetti:nextlib-media3ext:INSERT_VERSION_HERE") // To add media3 software decoders and extensions implementation("io.github.anilbeesetti:nextlib-mediainfo:INSERT_VERSION_HERE") // To get media info through ffmpeg } ``` -------------------------------- ### Integrate NextRenderersFactory with ExoPlayer Source: https://github.com/anilbeesetti/nextlib/blob/main/README.md Instantiate NextRenderersFactory and set it on the ExoPlayer builder to utilize FFmpeg decoders within your Media3 application. Ensure you have the necessary dependencies added. ```kotlin val renderersFactory = NextRenderersFactory(applicationContext) ExoPlayer.Builder(applicationContext) .setRenderersFactory(renderersFactory) .build() ``` -------------------------------- ### Add NextLib Dependencies to Android Project Source: https://context7.com/anilbeesetti/nextlib/llms.txt Include NextLib modules for FFmpeg codec support and media information extraction in your project's build.gradle.kts file. ```kotlin // build.gradle.kts dependencies { // FFmpeg decoders for Media3/ExoPlayer implementation("io.github.anilbeesetti:nextlib-media3ext:1.10.0-0.12.1") // Media info extraction (optional) implementation("io.github.anilbeesetti:nextlib-mediainfo:1.10.0-0.12.1") } ``` -------------------------------- ### Extract Media Information with MediaInfoBuilder Source: https://context7.com/anilbeesetti/nextlib/llms.txt Use MediaInfoBuilder to parse metadata from file paths, content URIs, or HTTP URLs. Always call release() on the resulting object to free native resources. ```kotlin import io.github.anilbeesetti.nextlib.mediainfo.MediaInfoBuilder import android.net.Uri // Extract media info from file path val mediaInfo = MediaInfoBuilder() .from("/storage/emulated/0/Movies/video.mkv") .build() mediaInfo?.let { info -> println("Format: ${info.format}") println("Duration: ${info.duration}ms") // Video stream details info.videoStream?.let { video -> println("Video codec: ${video.codecName}") println("Resolution: ${video.frameWidth}x${video.frameHeight}") println("Frame rate: ${video.frameRate} fps") println("Bit rate: ${video.bitRate} bps") println("Rotation: ${video.rotation}°") } // Audio streams info.audioStreams.forEach { audio -> println("Audio: ${audio.codecName}, ${audio.channels}ch, ${audio.sampleRate}Hz") println(" Language: ${audio.language ?: "unknown"}") println(" Layout: ${audio.channelLayout}") } // Subtitle streams info.subtitleStreams.forEach { subtitle -> println("Subtitle: ${subtitle.codecName}, ${subtitle.language ?: "unknown"}") } // Chapters info.chapters.forEach { chapter -> println("Chapter ${chapter.index}: ${chapter.title} (${chapter.start}-${chapter.end}ms)") } // Release resources when done info.release() } // Extract from content URI val uri = Uri.parse("content://media/external/video/media/123") val mediaInfoFromUri = MediaInfoBuilder() .from(context, uri) .build() // Extract from HTTP URL val remoteInfo = MediaInfoBuilder() .from("https://example.com/video.mp4") .build() ``` -------------------------------- ### Add NextLib Media3 Extensions Dependency (Groovy DSL) Source: https://github.com/anilbeesetti/nextlib/blob/main/README.md Include this dependency in your app's build.gradle file to add Media3 software decoders and extensions provided by NextLib. ```gradle dependencies { implementation "io.github.anilbeesetti:nextlib-media3ext:INSERT_VERSION_HERE" // To add media3 software decoders and extensions implementation "io.github.anilbeesetti:nextlib-mediainfo:INSERT_VERSION_HERE" // To get media info through ffmpeg } ``` -------------------------------- ### Link Libraries to Target Source: https://github.com/anilbeesetti/nextlib/blob/main/media3ext/src/main/cpp/CMakeLists.txt Links the main project library to system libraries (log, android) and the imported FFmpeg libraries. This ensures all dependencies are resolved during the build. ```cmake target_link_libraries(${CMAKE_PROJECT_NAME} # List libraries link to the target library log android ${ffmpeg_libs_names}) ``` -------------------------------- ### Define MediaInfo Data Classes Source: https://context7.com/anilbeesetti/nextlib/llms.txt Data classes representing video, audio, subtitle, and chapter metadata extracted from media containers. ```kotlin // VideoStream - Video track information data class VideoStream( val index: Int, // Stream index in container val title: String?, // Stream title metadata val codecName: String, // Codec name (e.g., "h264", "hevc") val language: String?, // ISO 639 language code val disposition: Int, // FFmpeg disposition flags val bitRate: Long, // Bits per second val frameRate: Double, // Frames per second val frameWidth: Int, // Width in pixels val frameHeight: Int, // Height in pixels val rotation: Int // Rotation degrees (0, 90, 180, 270) ) // AudioStream - Audio track information data class AudioStream( val index: Int, // Stream index val title: String?, // Stream title val codecName: String, // Codec name (e.g., "aac", "ac3", "dts") val language: String?, // Language code val disposition: Int, // FFmpeg disposition flags val bitRate: Long, // Bits per second val sampleFormat: String?,// Sample format (e.g., "fltp", "s16") val sampleRate: Int, // Samples per second (Hz) val channels: Int, // Number of channels val channelLayout: String?// Channel layout (e.g., "stereo", "5.1") ) // SubtitleStream - Subtitle track information data class SubtitleStream( val index: Int, // Stream index val title: String?, // Stream title val codecName: String, // Codec name (e.g., "subrip", "ass") val language: String?, // Language code val disposition: Int // FFmpeg disposition flags ) // Chapter - Chapter marker information data class Chapter( val index: Int, // Chapter index (0-based) val start: Long, // Start time in milliseconds val end: Long, // End time in milliseconds val title: String? // Chapter title ) ``` -------------------------------- ### Define FFmpeg Library Names Source: https://github.com/anilbeesetti/nextlib/blob/main/media3ext/src/main/cpp/CMakeLists.txt Lists the names of the FFmpeg libraries to be linked. These are used to dynamically add libraries later. ```cmake set( # List variable name ffmpeg_libs_names # Values in the list avutil avcodec swresample swscale) ``` -------------------------------- ### Add Main Native Library Source: https://github.com/anilbeesetti/nextlib/blob/main/media3ext/src/main/cpp/CMakeLists.txt Adds the main shared library for the project, listing the C/C++ source files. Ensure these source files exist in the specified relative paths. ```cmake add_library(${CMAKE_PROJECT_NAME} SHARED # List C/C++ source files with relative paths to this CMakeLists.txt. ffmain.cpp ffcommon.cpp ffaudio.cpp ffvideo.cpp) ``` -------------------------------- ### Import FFmpeg Shared Libraries Source: https://github.com/anilbeesetti/nextlib/blob/main/media3ext/src/main/cpp/CMakeLists.txt Iterates through the defined FFmpeg library names and creates imported shared library targets. This is necessary for linking external libraries. ```cmake foreach (ffmpeg_lib_name ${ffmpeg_libs_names}) add_library( ${ffmpeg_lib_name} SHARED IMPORTED) set_target_properties( ${ffmpeg_lib_name} PROPERTIES IMPORTED_LOCATION ${ffmpeg_libs}/lib${ffmpeg_lib_name}.so) endforeach () ``` -------------------------------- ### Include FFmpeg Headers Source: https://github.com/anilbeesetti/nextlib/blob/main/mediainfo/src/main/cpp/CMakeLists.txt Adds FFmpeg include directories to the build. This allows the compiler to find FFmpeg header files. ```cmake include_directories(${ffmpeg_dir}/include/${ANDROID_ABI}) ``` -------------------------------- ### Extract Video Frames with MediaInfoBuilder Source: https://context7.com/anilbeesetti/nextlib/llms.txt Retrieve Bitmaps from media files using getFrame or getFrameAt. Check supportsFrameLoading before attempting extraction. ```kotlin import io.github.anilbeesetti.nextlib.mediainfo.MediaInfoBuilder import android.graphics.Bitmap val mediaInfo = MediaInfoBuilder() .from("/storage/emulated/0/Movies/video.mp4") .build() mediaInfo?.let { info -> // Check if frame loading is supported if (info.supportsFrameLoading) { // Get frame at specific timestamp (5 seconds) val frameAt5s: Bitmap? = info.getFrame(durationMillis = 5000) // Get frame at default position (1/3 of duration) val defaultFrame: Bitmap? = info.getFrame() // Alternative method - getFrameAt lets FFmpeg allocate the bitmap val frameAt10s: Bitmap? = info.getFrameAt(durationMillis = 10000) // Use frames for thumbnails frameAt5s?.let { bitmap -> imageView.setImageBitmap(bitmap) } } // Always release when done info.release() } ``` -------------------------------- ### Define FFmpeg Library Names Source: https://github.com/anilbeesetti/nextlib/blob/main/mediainfo/src/main/cpp/CMakeLists.txt Lists the names of the FFmpeg libraries to be linked. These names are used when adding libraries. ```cmake set( # List variable name ffmpeg_libs_names # Values in the list avcodec avformat avutil swscale) ``` -------------------------------- ### Link Target Libraries Source: https://github.com/anilbeesetti/nextlib/blob/main/mediainfo/src/main/cpp/CMakeLists.txt Links the project library to other necessary libraries. This includes Android system libraries and the imported FFmpeg libraries. ```cmake target_link_libraries(${CMAKE_PROJECT_NAME} # List libraries link to the target library log jnigraphics ${ffmpeg_libs_names}) ``` -------------------------------- ### Adjust Subtitle Delay with NextRenderersFactory Source: https://context7.com/anilbeesetti/nextlib/llms.txt Configures subtitle synchronization offsets at runtime using the subtitleDelayMilliseconds property. ```kotlin import androidx.media3.exoplayer.ExoPlayer import io.github.anilbeesetti.nextlib.media3ext.ffdecoder.NextRenderersFactory import io.github.anilbeesetti.nextlib.media3ext.renderer.subtitleDelayMilliseconds // Create player with NextRenderersFactory val renderersFactory = NextRenderersFactory(applicationContext) val player = ExoPlayer.Builder(applicationContext) .setRenderersFactory(renderersFactory) .build() // Subtitles appear 2 seconds too early - delay them player.subtitleDelayMilliseconds = 2000L // Subtitles appear 1.5 seconds too late - advance them player.subtitleDelayMilliseconds = -1500L // Reset to original timing player.subtitleDelayMilliseconds = 0L // Check current delay setting val currentDelay = player.subtitleDelayMilliseconds println("Current subtitle delay: ${currentDelay}ms") // User controls example fun onDelayIncreaseClicked() { player.subtitleDelayMilliseconds += 250L // Add 250ms delay } fun onDelayDecreaseClicked() { player.subtitleDelayMilliseconds -= 250L // Reduce 250ms delay } ``` -------------------------------- ### Define Project Name Source: https://github.com/anilbeesetti/nextlib/blob/main/mediainfo/src/main/cpp/CMakeLists.txt Sets the name for the project. This name is used for targets and output files. ```cmake project("mediainfo") ``` -------------------------------- ### Declare Project Name Source: https://github.com/anilbeesetti/nextlib/blob/main/media3ext/src/main/cpp/CMakeLists.txt Declares and names the project. This name is used for the final library artifact. ```cmake project("media3ext") ``` -------------------------------- ### Retrieve Thumbnails and Artwork with MediaThumbnailRetriever Source: https://context7.com/anilbeesetti/nextlib/llms.txt Extract embedded album art or video frames using MediaThumbnailRetriever. Supports automatic resource management via use block or manual release. ```kotlin import io.github.anilbeesetti.nextlib.mediainfo.MediaThumbnailRetriever import android.graphics.BitmapFactory MediaThumbnailRetriever().use { retriever -> // Set data source from file path retriever.setDataSource("/storage/emulated/0/Music/song.mp3") // Get embedded album artwork (for audio files) val artworkBytes: ByteArray? = retriever.getEmbeddedPicture() artworkBytes?.let { bytes -> val artwork = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) albumCoverImageView.setImageBitmap(artwork) } } // Extract video frames at specific times MediaThumbnailRetriever().use { retriever -> retriever.setDataSource("/storage/emulated/0/Movies/video.mp4") // Get frame at 30 seconds (time in microseconds) val frameAt30s = retriever.getFrameAtTime(30_000_000L) // 30 seconds in microseconds // Get frame by index (zero-based) val firstFrame = retriever.getFrameAtIndex(0) val tenthFrame = retriever.getFrameAtIndex(9) frameAt30s?.let { bitmap -> thumbnailImageView.setImageBitmap(bitmap) } } // Using with content URI val uri = Uri.parse("content://media/external/video/media/456") MediaThumbnailRetriever().use { retriever -> retriever.setDataSource(context, uri) val thumbnail = retriever.getFrameAtTime(0L) // First frame // ... use thumbnail } // Manual resource management (alternative to use{}) val retriever = MediaThumbnailRetriever() try { retriever.setDataSource("https://example.com/video.mp4") val frame = retriever.getFrameAtTime(5_000_000L) // ... use frame } finally { retriever.release() // or retriever.close() } ``` -------------------------------- ### Set Minimum CMake Version Source: https://github.com/anilbeesetti/nextlib/blob/main/media3ext/src/main/cpp/CMakeLists.txt Specifies the minimum version of CMake required for the build. Ensure your CMake version meets this requirement. ```cmake cmake_minimum_required(VERSION 3.22.1) ``` -------------------------------- ### Set Shared Linker Flags Source: https://github.com/anilbeesetti/nextlib/blob/main/media3ext/src/main/cpp/CMakeLists.txt Configures linker flags for shared libraries, specifically setting the maximum page size. This can impact memory usage and performance. ```cmake set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384") ``` -------------------------------- ### Adjust Subtitle Speed for Drift Correction Source: https://context7.com/anilbeesetti/nextlib/llms.txt Corrects gradual timing drift or framerate mismatches using the subtitleSpeed property. ```kotlin import androidx.media3.exoplayer.ExoPlayer import io.github.anilbeesetti.nextlib.media3ext.ffdecoder.NextRenderersFactory import io.github.anilbeesetti.nextlib.media3ext.renderer.subtitleSpeed import io.github.anilbeesetti.nextlib.media3ext.renderer.subtitleDelayMilliseconds val renderersFactory = NextRenderersFactory(applicationContext) val player = ExoPlayer.Builder(applicationContext) .setRenderersFactory(renderersFactory) .build() // Subtitles sync at start but drift 10 seconds late by end of 60-min video // Speed them up by ~0.3% to catch up gradually player.subtitleSpeed = 1.003f // Subtitles sync at start but drift 5 seconds early by end // Slow them down player.subtitleSpeed = 0.95f // Reset to normal speed player.subtitleSpeed = 1.0f // Common framerate mismatch corrections: // Subtitles for 23.976fps playing on 25fps video (PAL speedup) player.subtitleSpeed = 25.0f / 23.976f // ≈ 1.043 // Subtitles for 24fps playing on 25fps video player.subtitleSpeed = 25.0f / 24.0f // ≈ 1.042 // Calculate required speed from observed drift fun calculateSubtitleSpeed( driftSeconds: Double, // How many seconds off at end (positive = late) videoDurationSeconds: Double ): Float { return (1.0 + (driftSeconds / videoDurationSeconds)).toFloat() } // Combined adjustment: fix initial offset AND gradual drift // Subtitles start 2s early AND drift 5s more by the end player.subtitleDelayMilliseconds = 2000L // Fix initial offset player.subtitleSpeed = 1.002f // Fix gradual drift ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.