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

◆ pull_frame()

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

Produce one frame into the container.

Writes pixel data into the container's frame buffer and marks it ready for processing. Returning false means no frame was available this cycle, which is not necessarily an error.

Parameters
containerTarget CameraContainer.
Returns
True if a new frame was written.

Implements MayaFlux::IO::CameraSource.

Definition at line 231 of file FFmpegCameraReader.cpp.

233{
234 if (!container)
235 return false;
236
237 std::shared_lock lock(m_ctx_mutex);
238 if (!m_video->is_codec_valid())
239 return false;
240
241 uint8_t* dest = container->mutable_frame_ptr();
242 if (!dest)
243 return false;
244
245 AVPacket* pkt = av_packet_alloc();
246 if (!pkt)
247 return false;
248
249 AVFrame* frame = av_frame_alloc();
250 if (!frame) {
251 av_packet_free(&pkt);
252 return false;
253 }
254
255 bool got_frame = false;
256
257 while (!got_frame) {
258 int ret = av_read_frame(m_demux->format_context, pkt);
259 if (ret < 0)
260 break;
261
262 if (pkt->stream_index != m_video->stream_index) {
263 av_packet_unref(pkt);
264 continue;
265 }
266
267 ret = avcodec_send_packet(m_video->codec_context, pkt);
268 av_packet_unref(pkt);
269
270 if (ret < 0 && ret != AVERROR(EAGAIN))
271 break;
272
273 ret = avcodec_receive_frame(m_video->codec_context, frame);
274 if (ret == AVERROR(EAGAIN))
275 continue;
276 if (ret < 0)
277 break;
278
279 if (!m_scaler_ready) {
280 if (!m_video->rebuild_scaler_from_frame(
281 frame,
282 static_cast<uint32_t>(frame->width),
283 static_cast<uint32_t>(frame->height))) {
285 "FFmpegCameraReader: scaler init failed: {}",
286 m_video->last_error());
287 break;
288 }
289 const size_t buf_bytes = static_cast<size_t>(m_video->out_linesize) * m_video->out_height;
290 m_sws_buf.assign(buf_bytes, 0);
291 m_scaler_ready = true;
292 }
293
294 uint8_t* sws_dst[1] = { m_sws_buf.data() };
295 int sws_stride[1] = { m_video->out_linesize };
296
297 sws_scale(m_video->sws_context,
298 frame->data, frame->linesize,
299 0, static_cast<int>(m_video->height),
300 sws_dst, sws_stride);
301
302 const int packed_stride = static_cast<int>(m_video->out_width * m_video->out_bytes_per_pixel);
303
304 if (m_video->out_linesize == packed_stride) {
305 std::memcpy(dest, m_sws_buf.data(),
306 static_cast<size_t>(packed_stride) * m_video->out_height);
307 } else {
308 for (uint32_t row = 0; row < m_video->out_height; ++row) {
309 std::memcpy(
310 dest + static_cast<size_t>(row) * packed_stride,
311 m_sws_buf.data() + static_cast<size_t>(row) * m_video->out_linesize,
312 static_cast<size_t>(packed_stride));
313 }
314 }
315
316 container->mark_ready_for_processing(true);
317 got_frame = true;
318 }
319
320 av_frame_free(&frame);
321 av_packet_free(&pkt);
322
323 return got_frame;
324}
#define MF_ERROR(comp, ctx,...)
std::shared_ptr< FFmpegDemuxContext > m_demux
std::shared_ptr< VideoStreamContext > m_video
@ 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: