MayaFlux 0.5.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 385 of file VideoFileReader.cpp.

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