Initial commit
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user