MayaFlux 0.4.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 379 of file VideoFileReader.cpp.

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