# FadCam fMP4 Recording Performance: MediaCodec and Fragmented MP4 Optimization

> Discover FadCam's fMP4 recording performance. Learn how it uses MediaCodec, zero-copy Surface, fragmented MP4, and optimized I/O for efficient video capture on Android.

- Repository: [Faded/FadCam](https://github.com/anonfaded/FadCam)
- Tags: performance
- Published: 2026-05-13

---

**FadCam achieves high-performance fMP4 recording on Android by combining hardware-accelerated MediaCodec encoding with zero-copy Surface input, fragmented MP4 segmentation for streaming, cache-first disk I/O, and background FFmpeg remuxing with atomic task counting.**

FadCam (anonfaded/FadCam) implements a sophisticated video recording pipeline designed for real-time **fMP4 recording performance** across diverse Android hardware. The application leverages **fragmented MP4 (fMP4)** containerization to balance encoding efficiency, storage management, and network streaming capabilities. Understanding these architectural decisions helps developers optimize their own MediaCodec implementations while maintaining smooth recording even on low-power devices.

## Hardware-Accelerated Encoding with MediaCodec

At the core of FadCam's performance strategy is the `GLRecordingPipeline` class, which orchestrates hardware-accelerated video encoding without burdening the CPU.

### Zero-Copy Surface Input

The pipeline eliminates expensive memory copies by feeding frames directly into the encoder via a `Surface` object. In [`app/src/main/java/com/fadcam/opengl/GLRecordingPipeline.java`](https://github.com/anonfaded/FadCam/blob/main/app/src/main/java/com/fadcam/opengl/GLRecordingPipeline.java), the encoder initialization uses:

```java
// Line 1274-1275
videoEncoder = MediaCodec.createEncoderByType(currentMimeType);
videoEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);

```

By avoiding `ByteBuffer` copies in Java memory, this approach keeps the main thread responsive and reduces garbage collection pressure during long recording sessions.

### Adaptive Bitrate Control

FadCam selects between constant bitrate (CBR) and variable bitrate (VBR) modes based on device capabilities (lines 1143-1144 in [`GLRecordingPipeline.java`](https://github.com/anonfaded/FadCam/blob/main/GLRecordingPipeline.java)). **CBR mode** provides predictable file sizes for storage-constrained environments, while **VBR mode** adapts to scene complexity, delivering better visual quality without over-taxing the encoder during high-motion sequences.

## Fragmented MP4 Architecture for Streaming

The fMP4 container format enables FadCam to support both local recording and live streaming simultaneously without duplicating the encoding effort.

### Streaming-Optimized Init Segments

The `FragmentedMp4MuxerWrapper` (located at [`app/src/main/java/com/fadcam/playback/FragmentedMp4MuxerWrapper.java`](https://github.com/anonfaded/FadCam/blob/main/app/src/main/java/com/fadcam/playback/FragmentedMp4MuxerWrapper.java)) generates an `init.mp4` initialization segment separate from media fragments. This segment is served statically by [`LiveM3U8Server.java`](https://github.com/anonfaded/FadCam/blob/main/LiveM3U8Server.java) (lines 99-132), allowing HLS players to begin playback immediately while the recording continues. Because the init segment remains unencrypted (`SegmentEncryptor.java:26`), clients avoid decryption overhead during stream startup.

### Configurable Segment Boundaries

To prevent individual files from growing unwieldy, FadCam implements configurable segment sizing in [`GLRecordingPipeline.java`](https://github.com/anonfaded/FadCam/blob/main/GLRecordingPipeline.java) (lines 367-370). The `maxFileSizeBytes` parameter ensures that no single fragment exceeds memory-safe thresholds, enabling efficient fast-forward and rewind operations without loading massive files into memory.

## Disk I/O and Storage Optimization

FadCam minimizes storage-related performance bottlenecks through strategic file handling and optimized directory scanning.

### Cache-First Write Strategy

When operating in `STREAM_ONLY` mode, [`RecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/RecordingService.java) (lines 6611-6613) writes to temporary cache files before moving to final storage:

```java
File outputFile = new File(getCacheDir(),
        "stream_temp_" + System.currentTimeMillis() + ".mp4");
pipelineBuilder.setOutputFile(outputFile.getAbsolutePath());

```

This approach leverages the faster internal storage partition for active recording, deferring slower Storage Access Framework (SAF) operations until the recording completes.

### High-Performance File Scanning

The `FastFileScanner` class ([`app/src/main/java/com/fadcam/data/FastFileScanner.java`](https://github.com/anonfaded/FadCam/blob/main/app/src/main/java/com/fadcam/data/FastFileScanner.java)) replaces the standard `DocumentFile.listFiles()` method with bulk `File` scanning (lines 31-456). This optimization reduces inter-process communication (IPC) calls when enumerating large video libraries, preventing UI freezes on devices with thousands of recordings.

## Background Processing and Thread Safety

Post-processing operations utilize FFmpegKit with careful thread management to prevent UI blocking.

### Atomic Task Counting

[`RecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/RecordingService.java) maintains an `AtomicInteger` named `ffmpegProcessingTaskCount` (line 153) to track background operations. Before executing FFmpeg commands, the counter increments; upon completion, it decrements. The application checks this count before updating UI elements (line 5309), ensuring that CPU-intensive remuxing never blocks the main thread.

### Copy-Only Remuxing

The `FragmentedMp4Remuxer` ([`app/src/main/java/com/fadcam/playback/FragmentedMp4Remuxer.java`](https://github.com/anonfaded/FadCam/blob/main/app/src/main/java/com/fadcam/playback/FragmentedMp4Remuxer.java)) performs format conversion without re-encoding:

```java
String ffmpegCmd = String.format("-y -i %s -c copy %s", inputPath, outputPath);
FFmpegKit.executeAsync(ffmpegCmd, session -> {
    // Background completion callback
});

```

Using the `-c copy` flag avoids decode/encode cycles, reducing processing time from minutes to seconds even on low-power devices.

## Memory Management Strategies

FadCam implements aggressive memory conservation during bitmap operations to prevent OutOfMemoryError crashes during extended recording sessions.

### Bitmap Recycling

When capturing photos from live recordings (`RecordingService.java:22-28`), bitmaps are processed on background handlers, scaled to target dimensions, and immediately recycled via `bitmap.recycle()`. This pattern appears throughout the codebase, including `AudioWaveformView` and `AudioExtractor`, maintaining a minimal Java heap footprint.

## Summary

- **Hardware-accelerated encoding** via `MediaCodec.createEncoderByType()` offloads compression to the GPU, reducing CPU utilization.
- **Zero-copy Surface input** eliminates expensive `ByteBuffer` operations and keeps the main thread responsive.
- **Fragmented MP4 containers** enable simultaneous recording and streaming through separate init and media segments.
- **Cache-first file writes** minimize SAF overhead by writing to internal storage before moving to external destinations.
- **Atomic task counting** ensures FFmpeg operations run on background threads without blocking UI updates.
- **Copy-only remuxing** provides fast post-processing without re-encoding video streams.

## Frequently Asked Questions

### How does FadCam prevent video encoding from slowing down the Android UI?

FadCam utilizes `MediaCodec.createEncoderByType()` with Surface input in [`GLRecordingPipeline.java`](https://github.com/anonfaded/FadCam/blob/main/GLRecordingPipeline.java), which offloads encoding to dedicated hardware. This zero-copy approach prevents the main thread from processing raw frame data. Additionally, all FFmpeg operations run asynchronously with an `AtomicInteger` task counter (`RecordingService.java:153`) that guards UI updates until background work completes.

### What makes fragmented MP4 (fMP4) better for streaming than standard MP4?

Standard MP4 files require the complete file to be written before the metadata (moov atom) is valid, preventing playback until recording finishes. FadCam's `FragmentedMp4MuxerWrapper` writes an `init.mp4` segment containing metadata upfront, followed by media fragments. This structure allows `LiveM3U8Server` to serve HLS streams immediately while recording continues, with unencrypted init segments (`SegmentEncryptor.java:26`) ensuring minimal client startup delay.

### Why does FadCam write recordings to cache before moving to final storage?

Writing directly to external storage via Storage Access Framework (SAF) introduces significant latency due to repeated IPC calls. [`RecordingService.java`](https://github.com/anonfaded/FadCam/blob/main/RecordingService.java) (lines 6611-6613) writes to `getCacheDir()` first, leveraging the faster internal storage partition. The temporary file moves to its final destination only after recording stops, batching the slower SAF operations and preventing frame drops during active capture.

### How does FadCam handle large video libraries without UI freezing?

The `FastFileScanner` class ([`app/src/main/java/com/fadcam/data/FastFileScanner.java`](https://github.com/anonfaded/FadCam/blob/main/app/src/main/java/com/fadcam/data/FastFileScanner.java)) replaces `DocumentFile.listFiles()` with bulk `File` scanning across lines 31-456. This reduces IPC overhead when enumerating thousands of video files, while `FFprobeKit` media information caching in [`VideoSourceBottomSheet.java`](https://github.com/anonfaded/FadCam/blob/main/VideoSourceBottomSheet.java) (lines 719-721) prevents repeated metadata extraction during audio processing tasks.