MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ pull_frame()

bool MayaFlux::IO::CameraReader::pull_frame ( const std::shared_ptr< Kakshya::CameraContainer > &  container)

Decode one frame from the device into the container's m_data[0].

Pumps packets until one decoded frame is available, converts to RGBA via swscale into container->mutable_frame_ptr(), then calls container->mark_ready_for_processing(true). Returns false on EAGAIN (no frame yet) — not an error, just no data available this cycle.

The caller is responsible for invoking this once per graphics cycle, before the container's process_default() is triggered by downstream consumers. Typical integration: register as a graphics pre_process_hook or call explicitly before buffer processing.

Parameters
containerTarget CameraContainer.
Returns
True if a new frame was written, false if no frame was available.

Definition at line 143 of file CameraReader.cpp.

145{
146 if (!container)
147 return false;
148
149 std::shared_lock lock(m_ctx_mutex);
150 if (!m_video->is_codec_valid())
151 return false;
152
153 uint8_t* dest = container->mutable_frame_ptr();
154 if (!dest)
155 return false;
156
157 AVPacket* pkt = av_packet_alloc();
158 if (!pkt)
159 return false;
160
161 AVFrame* frame = av_frame_alloc();
162 if (!frame) {
163 av_packet_free(&pkt);
164 return false;
165 }
166
167 bool got_frame = false;
168
169 while (!got_frame) {
170 int ret = av_read_frame(m_demux->format_context, pkt);
171 if (ret < 0)
172 break;
173
174 if (pkt->stream_index != m_video->stream_index) {
175 av_packet_unref(pkt);
176 continue;
177 }
178
179 ret = avcodec_send_packet(m_video->codec_context, pkt);
180 av_packet_unref(pkt);
181
182 if (ret < 0 && ret != AVERROR(EAGAIN))
183 break;
184
185 ret = avcodec_receive_frame(m_video->codec_context, frame);
186 if (ret == AVERROR(EAGAIN))
187 continue;
188 if (ret < 0)
189 break;
190
191 if (!m_scaler_ready) {
192 if (!m_video->rebuild_scaler_from_frame(
193 frame,
194 static_cast<uint32_t>(frame->width),
195 static_cast<uint32_t>(frame->height))) {
197 "CameraReader: scaler init failed: {}",
198 m_video->last_error());
199 break;
200 }
201 const size_t buf_bytes = static_cast<size_t>(m_video->out_linesize) * m_video->out_height;
202 m_sws_buf.assign(buf_bytes, 0);
203 m_scaler_ready = true;
204 }
205
206 uint8_t* sws_dst[1] = { m_sws_buf.data() };
207 int sws_stride[1] = { m_video->out_linesize };
208
209 sws_scale(m_video->sws_context,
210 frame->data, frame->linesize,
211 0, static_cast<int>(m_video->height),
212 sws_dst, sws_stride);
213
214 const int packed_stride = static_cast<int>(m_video->out_width * m_video->out_bytes_per_pixel);
215
216 if (m_video->out_linesize == packed_stride) {
217 std::memcpy(dest, m_sws_buf.data(),
218 static_cast<size_t>(packed_stride) * m_video->out_height);
219 } else {
220 for (uint32_t row = 0; row < m_video->out_height; ++row) {
221 std::memcpy(
222 dest + static_cast<size_t>(row) * packed_stride,
223 m_sws_buf.data() + static_cast<size_t>(row) * m_video->out_linesize,
224 static_cast<size_t>(packed_stride));
225 }
226 }
227
228 container->mark_ready_for_processing(true);
229 got_frame = true;
230 }
231
232 av_frame_free(&frame);
233 av_packet_free(&pkt);
234
235 return got_frame;
236}
#define MF_ERROR(comp, ctx,...)
std::vector< uint8_t > m_sws_buf
std::shared_mutex m_ctx_mutex
std::shared_ptr< VideoStreamContext > m_video
std::shared_ptr< FFmpegDemuxContext > m_demux
@ Runtime
General runtime operations (default fallback)
@ IO
Networking, file handling, streaming.

References MayaFlux::Journal::IO, m_ctx_mutex, m_demux, m_scaler_ready, m_sws_buf, m_video, MF_ERROR, and MayaFlux::Journal::Runtime.

Referenced by decode_thread_func().

+ Here is the caller graph for this function: