101 lines
3.2 KiB
C++
101 lines
3.2 KiB
C++
#ifndef VIDEO_DECODER_H
|
|
#define VIDEO_DECODER_H
|
|
|
|
#include <cstdint>
|
|
#include <cstddef>
|
|
#include <string>
|
|
|
|
// Video decoder using NDK MediaCodec API
|
|
// Decodes video files to YUV420 frames and writes to shared memory ring buffer
|
|
// for consumption by the HAL hook in the camera provider process.
|
|
|
|
namespace video_decoder {
|
|
|
|
// Shared memory ring buffer header
|
|
// This structure is placed at the beginning of the memfd shared memory region.
|
|
struct RingBufferHeader {
|
|
uint32_t magic; // 0xCAM2MAGC
|
|
uint32_t version; // Header version (1)
|
|
uint32_t frame_count; // Number of frame slots in ring buffer
|
|
uint32_t frame_width; // Decoded frame width
|
|
uint32_t frame_height; // Decoded frame height
|
|
uint32_t frame_size; // Size of one YUV420 frame (w * h * 3/2)
|
|
uint32_t write_index; // Atomic: next slot to write
|
|
uint32_t read_index; // Atomic: last slot read by consumer
|
|
uint32_t sequence; // Monotonically increasing frame counter
|
|
uint32_t flags; // Bit flags (bit 0: decoder running)
|
|
uint64_t last_timestamp; // Timestamp of last written frame (us)
|
|
uint8_t reserved[216]; // Padding to 256 bytes
|
|
};
|
|
|
|
static constexpr uint32_t RING_MAGIC = 0xCA22A61C;
|
|
static constexpr uint32_t RING_VERSION = 1;
|
|
static constexpr uint32_t RING_FRAME_COUNT = 4;
|
|
static constexpr uint32_t RING_HEADER_SIZE = 256;
|
|
static constexpr uint32_t FLAG_DECODER_RUNNING = 0x1;
|
|
|
|
// Calculate total shared memory size needed
|
|
inline size_t calc_shmem_size(uint32_t width, uint32_t height, uint32_t frame_count = RING_FRAME_COUNT) {
|
|
size_t frame_size = (size_t)width * height * 3 / 2; // YUV420
|
|
return RING_HEADER_SIZE + (frame_size * frame_count);
|
|
}
|
|
|
|
// Get pointer to frame slot in shared memory
|
|
inline uint8_t* get_frame_ptr(uint8_t* base, uint32_t index, uint32_t frame_size, uint32_t frame_count) {
|
|
return base + RING_HEADER_SIZE + ((index % frame_count) * frame_size);
|
|
}
|
|
|
|
// Decoder state
|
|
struct DecoderState {
|
|
std::string video_path;
|
|
int32_t width;
|
|
int32_t height;
|
|
int32_t rotation; // 0, 90, 180, 270
|
|
bool loop;
|
|
bool running;
|
|
|
|
// Shared memory
|
|
int shmem_fd;
|
|
uint8_t* shmem_base;
|
|
size_t shmem_size;
|
|
RingBufferHeader* header;
|
|
|
|
// Decoder thread
|
|
pthread_t decoder_thread;
|
|
};
|
|
|
|
// Initialize the video decoder
|
|
// Returns 0 on success, negative on error
|
|
int init_decoder(const char* video_path, bool loop = true);
|
|
|
|
// Start the decoder thread
|
|
// Returns 0 on success
|
|
int start_decoder();
|
|
|
|
// Stop the decoder thread
|
|
void stop_decoder();
|
|
|
|
// Release decoder resources
|
|
void release_decoder();
|
|
|
|
// Get the shared memory fd (for passing to other processes)
|
|
// Returns -1 if not initialized
|
|
int get_shmem_fd();
|
|
|
|
// Get decoder state info
|
|
int get_decoder_width();
|
|
int get_decoder_height();
|
|
bool is_decoder_running();
|
|
|
|
// Write a YUV420 frame to the shared memory ring buffer
|
|
// Called internally by the decoder thread
|
|
// y_data, u_data, v_data: pointers to Y, U, V planes
|
|
// y_stride, uv_stride: stride of Y and UV planes
|
|
// width, height: frame dimensions
|
|
bool write_frame_to_ring(const uint8_t* y_data, const uint8_t* u_data, const uint8_t* v_data,
|
|
int y_stride, int uv_stride, int width, int height);
|
|
|
|
} // namespace video_decoder
|
|
|
|
#endif // VIDEO_DECODER_H
|