MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
FFmpegDemuxContext.hpp
Go to the documentation of this file.
1#pragma once
2
3extern "C" {
4struct AVFormatContext;
5struct AVStream;
6struct AVDictionaryEntry;
7struct AVDictionary;
8}
9
11
12namespace MayaFlux::IO {
13
14/**
15 * @class FFmpegDemuxContext
16 * @brief RAII owner of a single AVFormatContext and associated demux state.
17 *
18 * Encapsulates all format-level (container) FFmpeg operations:
19 * - Opening and probing a media file via libavformat
20 * - Enumerating streams and selecting best stream per media type
21 * - Seeking at the format level (av_seek_frame)
22 * - Extracting container-level metadata tags and chapter regions
23 * - FFmpeg library initialization (once per process)
24 *
25 * Does NOT own any codec context, resampler, or scaler — those are
26 * domain-specific and belong to AudioStreamContext / VideoStreamContext.
27 *
28 * Shared ownership via shared_ptr allows multiple stream contexts to
29 * reference the same demuxer without duplicating the format state.
30 * Not copyable or movable; always heap-allocated through make_shared.
31 */
32class MAYAFLUX_API FFmpegDemuxContext {
33public:
34 FFmpegDemuxContext() = default;
36
41
42 // =========================================================================
43 // Lifecycle
44 // =========================================================================
45
46 /**
47 * @brief Open a media file and probe stream information.
48 * @param filepath Absolute or relative path to the media file.
49 * @return True on success; false sets internal error string.
50 */
51 bool open(const std::string& filepath);
52
53 /**
54 * @brief Close the format context and release all demux resources.
55 * Safe to call multiple times.
56 */
57 void close();
58
59 /**
60 * @brief True if the format context is open and stream info was found.
61 */
62 [[nodiscard]] bool is_open() const { return format_context != nullptr; }
63
64 /**
65 * @brief Open an FFmpeg device input (camera, screen capture, etc.).
66 *
67 * Calls av_find_input_format() then avformat_open_input() with the
68 * supplied options dict. avdevice_register_all() must have been called
69 * before this method.
70 *
71 * @param device_name Platform device string (e.g. "/dev/video0").
72 * @param format_name FFmpeg input format name (e.g. "v4l2", "avfoundation").
73 * @param options AVDictionary of format options; consumed and freed on return.
74 * @return True on success.
75 */
76 [[nodiscard]] bool open_device(const std::string& device_name,
77 const std::string& format_name,
78 AVDictionary** options = nullptr);
79
80 // =========================================================================
81 // Stream discovery
82 // =========================================================================
83
84 /**
85 * @brief Find the best stream of the requested media type.
86 * @param media_type AVMediaType value (AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_VIDEO, …)
87 * @param out_codec Receives a pointer to the matched codec (may be nullptr if
88 * caller does not need it).
89 * @return Stream index ≥ 0 on success, negative on failure.
90 */
91 [[nodiscard]] int find_best_stream(int media_type, const void** out_codec = nullptr) const;
92
93 /**
94 * @brief Access a stream by index.
95 * @param index Stream index in format_context->streams[].
96 * @return Pointer to AVStream, or nullptr if index is out of range.
97 */
98 [[nodiscard]] AVStream* get_stream(int index) const;
99
100 /**
101 * @brief Number of streams in the container.
102 */
103 [[nodiscard]] unsigned int stream_count() const;
104
105 // =========================================================================
106 // Seeking
107 // =========================================================================
108
109 /**
110 * @brief Seek to the nearest keyframe at or before the given timestamp.
111 * @param stream_index Target stream index.
112 * @param timestamp Timestamp in the stream's time_base units.
113 * @return True on success.
114 */
115 bool seek(int stream_index, int64_t timestamp);
116
117 /**
118 * @brief Flush the demuxer's internal read buffers.
119 * Call after seek before reading new packets.
120 */
121 void flush();
122
123 // =========================================================================
124 // Metadata / regions
125 // =========================================================================
126
127 /**
128 * @brief Extract container-level metadata tags into a FileMetadata attributes map.
129 * @param out_metadata Target metadata struct; attributes field is populated.
130 */
131 void extract_container_metadata(FileMetadata& out_metadata) const;
132
133 /**
134 * @brief Extract chapter information as FileRegion entries.
135 * @return Vector of FileRegion with type="chapter".
136 */
137 [[nodiscard]] std::vector<FileRegion> extract_chapter_regions() const;
138
139 /**
140 * @brief Total container duration in seconds, or 0 if unknown.
141 */
142 [[nodiscard]] double duration_seconds() const;
143
144 // =========================================================================
145 // Error
146 // =========================================================================
147
148 [[nodiscard]] const std::string& last_error() const { return m_last_error; }
149
150 // =========================================================================
151 // FFmpeg global init (idempotent, thread-safe)
152 // =========================================================================
153
154 /**
155 * @brief Initialise FFmpeg logging level once per process.
156 * Called automatically by the constructor of every stream context.
157 */
158 static void init_ffmpeg();
159
160 // =========================================================================
161 // Raw handle — accessible to stream contexts for packet reading
162 // =========================================================================
163
164 AVFormatContext* format_context = nullptr; ///< Owned; freed in destructor.
165
166private:
167 std::string m_last_error;
168
169 static std::atomic<bool> s_ffmpeg_initialized;
170 static std::mutex s_ffmpeg_init_mutex;
171};
172
173} // namespace MayaFlux::IO
FFmpegDemuxContext & operator=(FFmpegDemuxContext &&)=delete
const std::string & last_error() const
FFmpegDemuxContext & operator=(const FFmpegDemuxContext &)=delete
FFmpegDemuxContext(FFmpegDemuxContext &&)=delete
static std::atomic< bool > s_ffmpeg_initialized
FFmpegDemuxContext(const FFmpegDemuxContext &)=delete
bool is_open() const
True if the format context is open and stream info was found.
RAII owner of a single AVFormatContext and associated demux state.
Generic metadata structure for any file type.