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.
381{
384 return 0;
385
386 const size_t required =
static_cast<size_t>(
m_video->out_linesize) *
m_video->out_height;
389
390 const size_t frame_bytes = vc.get_frame_byte_size();
391 const int packed_stride = static_cast<int>(
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 {
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,
428 static_cast<size_t>(packed_stride));
429 }
430 }
431
432 vc.commit_frame(idx);
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_mutex m_context_mutex
std::shared_ptr< VideoStreamContext > m_video
std::atomic< uint64_t > m_decode_head