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

◆ decode_batch()

uint64_t MayaFlux::IO::VideoFileReader::decode_batch ( Kakshya::VideoFileContainer vc,
uint64_t  batch_size 
)
private

Decode up to batch_size frames starting at m_decode_head.

Pumps packets in a loop, draining multiple frames per packet batch. Returns the number of frames actually decoded.

Definition at line 374 of file VideoFileReader.cpp.

376{
377 std::shared_lock ctx_lock(m_context_mutex);
378 if (!m_demux || !m_video || !m_video->is_valid())
379 return 0;
380
381 const size_t required = static_cast<size_t>(m_video->out_linesize) * m_video->out_height;
382 if (m_sws_buf.size() < required)
383 m_sws_buf.resize(required);
384
385 const size_t frame_bytes = vc.get_frame_byte_size();
386 const int packed_stride = static_cast<int>(
387 m_video->out_width * m_video->out_bytes_per_pixel);
388
389 uint64_t decoded = 0;
390
391 AVPacket* pkt = av_packet_alloc();
392 AVFrame* frame = av_frame_alloc();
393 if (!pkt || !frame) {
394 av_packet_free(&pkt);
395 av_frame_free(&frame);
396 return 0;
397 }
398
399 uint8_t* sws_dst[1] = { m_sws_buf.data() };
400 int sws_stride[1] = { m_video->out_linesize };
401
402 auto write_frame_to_ring = [&]() -> bool {
403 uint64_t idx = m_decode_head.load();
404 if (idx >= vc.get_total_source_frames())
405 return false;
406
407 uint8_t* dest = vc.mutable_slot_ptr(idx);
408 if (!dest)
409 return false;
410
411 sws_scale(m_video->sws_context,
412 frame->data, frame->linesize,
413 0, static_cast<int>(m_video->height),
414 sws_dst, sws_stride);
415
416 if (m_video->out_linesize == packed_stride) {
417 std::memcpy(dest, m_sws_buf.data(), frame_bytes);
418 } else {
419 for (uint32_t row = 0; row < m_video->out_height; ++row) {
420 std::memcpy(
421 dest + static_cast<size_t>(row) * packed_stride,
422 m_sws_buf.data() + static_cast<size_t>(row) * m_video->out_linesize,
423 static_cast<size_t>(packed_stride));
424 }
425 }
426
427 vc.commit_frame(idx);
428 m_decode_head.fetch_add(1);
429 ++decoded;
430
431 av_frame_unref(frame);
432 return true;
433 };
434
435 while (decoded < batch_size) {
436 int ret = av_read_frame(m_demux->format_context, pkt);
437
438 if (ret < 0) {
439 if (ret == AVERROR_EOF) {
440 avcodec_send_packet(m_video->codec_context, nullptr);
441 } else {
442 break;
443 }
444 } else if (pkt->stream_index != m_video->stream_index) {
445 av_packet_unref(pkt);
446 continue;
447 } else {
448 ret = avcodec_send_packet(m_video->codec_context, pkt);
449 av_packet_unref(pkt);
450 if (ret < 0 && ret != AVERROR(EAGAIN))
451 continue;
452 }
453
454 while (decoded < batch_size) {
455 ret = avcodec_receive_frame(m_video->codec_context, frame);
456 if (ret == AVERROR(EAGAIN))
457 break;
458 if (ret == AVERROR_EOF)
459 goto done;
460 if (ret < 0) {
461 av_frame_unref(frame);
462 break;
463 }
464
465 if (!write_frame_to_ring())
466 goto done;
467 }
468
469 if (ret == AVERROR_EOF)
470 break;
471 }
472
473done:
474 av_packet_free(&pkt);
475 av_frame_free(&frame);
476 return decoded;
477}
std::vector< uint8_t > m_sws_buf
One-frame sws scratch buffer (padded linesize, reused by decode thread).
std::shared_ptr< FFmpegDemuxContext > m_demux
std::shared_ptr< VideoStreamContext > m_video
std::atomic< uint64_t > m_decode_head

References MayaFlux::Kakshya::VideoStreamContainer::commit_frame(), MayaFlux::Kakshya::VideoStreamContainer::get_frame_byte_size(), MayaFlux::Kakshya::VideoStreamContainer::get_total_source_frames(), m_context_mutex, m_decode_head, m_demux, m_sws_buf, m_video, and MayaFlux::Kakshya::VideoStreamContainer::mutable_slot_ptr().

Referenced by decode_thread_func(), load_into_container(), and seek().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: