MayaFlux 0.5.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 152 of file CameraReader.cpp.

154{
155 if (!container)
156 return false;
157
158 std::shared_lock lock(m_ctx_mutex);
159 if (!m_video->is_codec_valid())
160 return false;
161
162 uint8_t* dest = container->mutable_frame_ptr();
163 if (!dest)
164 return false;
165
166 AVPacket* pkt = av_packet_alloc();
167 if (!pkt)
168 return false;
169
170 AVFrame* frame = av_frame_alloc();
171 if (!frame) {
172 av_packet_free(&pkt);
173 return false;
174 }
175
176 bool got_frame = false;
177
178 while (!got_frame) {
179 int ret = av_read_frame(m_demux->format_context, pkt);
180 if (ret < 0)
181 break;
182
183 if (pkt->stream_index != m_video->stream_index) {
184 av_packet_unref(pkt);
185 continue;
186 }
187
188 ret = avcodec_send_packet(m_video->codec_context, pkt);
189 av_packet_unref(pkt);
190
191 if (ret < 0 && ret != AVERROR(EAGAIN))
192 break;
193
194 ret = avcodec_receive_frame(m_video->codec_context, frame);
195 if (ret == AVERROR(EAGAIN))
196 continue;
197 if (ret < 0)
198 break;
199
200 if (!m_scaler_ready) {
201 if (!m_video->rebuild_scaler_from_frame(
202 frame,
203 static_cast<uint32_t>(frame->width),
204 static_cast<uint32_t>(frame->height))) {
206 "CameraReader: scaler init failed: {}",
207 m_video->last_error());
208 break;
209 }
210 const size_t buf_bytes = static_cast<size_t>(m_video->out_linesize) * m_video->out_height;
211 m_sws_buf.assign(buf_bytes, 0);
212 m_scaler_ready = true;
213 }
214
215 uint8_t* sws_dst[1] = { m_sws_buf.data() };
216 int sws_stride[1] = { m_video->out_linesize };
217
218 sws_scale(m_video->sws_context,
219 frame->data, frame->linesize,
220 0, static_cast<int>(m_video->height),
221 sws_dst, sws_stride);
222
223 const int packed_stride = static_cast<int>(m_video->out_width * m_video->out_bytes_per_pixel);
224
225 if (m_video->out_linesize == packed_stride) {
226 std::memcpy(dest, m_sws_buf.data(),
227 static_cast<size_t>(packed_stride) * m_video->out_height);
228 } else {
229 for (uint32_t row = 0; row < m_video->out_height; ++row) {
230 std::memcpy(
231 dest + static_cast<size_t>(row) * packed_stride,
232 m_sws_buf.data() + static_cast<size_t>(row) * m_video->out_linesize,
233 static_cast<size_t>(packed_stride));
234 }
235 }
236
237 container->mark_ready_for_processing(true);
238 got_frame = true;
239 }
240
241 av_frame_free(&frame);
242 av_packet_free(&pkt);
243
244 return got_frame;
245}
#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: