| 527 | AVBufferRef* DeviceContext() const { return hw_device_context_; } |
| 528 | |
| 529 | bool NextFrame(ScopedFrame& frame, double& decode_ms) { |
| 530 | const auto start = Clock::now(); |
| 531 | AVFrame* decoded = av_frame_alloc(); |
| 532 | if (!decoded) { |
| 533 | throw std::runtime_error("Unable to allocate decode frame"); |
| 534 | } |
| 535 | |
| 536 | while (true) { |
| 537 | const int receive_result = avcodec_receive_frame(codec_context_, decoded); |
| 538 | if (receive_result == 0) { |
| 539 | const AVPixFmtDescriptor* desc = |
| 540 | av_pix_fmt_desc_get(static_cast<AVPixelFormat>(decoded->format)); |
| 541 | if ((desc && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) || decoded->hw_frames_ctx) |
| 542 | decoded_hw_frames_ = true; |
| 543 | decoded->pts = frame_counter_++; |
| 544 | frame = ScopedFrame(decoded); |
| 545 | decode_ms = std::chrono::duration<double, std::milli>(Clock::now() - start).count(); |
| 546 | return true; |
| 547 | } |
| 548 | if (receive_result == AVERROR_EOF) { |
| 549 | av_frame_free(&decoded); |
| 550 | decode_ms = std::chrono::duration<double, std::milli>(Clock::now() - start).count(); |
| 551 | return false; |
| 552 | } |
| 553 | if (receive_result != AVERROR(EAGAIN)) { |
| 554 | const std::string err = AvError(receive_result); |
| 555 | av_frame_free(&decoded); |
| 556 | throw std::runtime_error("avcodec_receive_frame failed: " + err); |
| 557 | } |
| 558 | |
| 559 | int send_result = 0; |
| 560 | if (!draining_) { |
| 561 | while (true) { |
| 562 | send_result = av_read_frame(format_context_, packet_.get()); |
| 563 | if (send_result < 0) { |
| 564 | draining_ = true; |
| 565 | send_result = avcodec_send_packet(codec_context_, nullptr); |
| 566 | break; |
| 567 | } |
| 568 | if (packet_.get()->stream_index != video_stream_index_) { |
| 569 | av_packet_unref(packet_.get()); |
| 570 | continue; |
| 571 | } |
| 572 | |
| 573 | send_result = avcodec_send_packet(codec_context_, packet_.get()); |
| 574 | av_packet_unref(packet_.get()); |
| 575 | break; |
| 576 | } |
| 577 | } else { |
| 578 | send_result = avcodec_send_packet(codec_context_, nullptr); |
| 579 | } |
| 580 | |
| 581 | if (send_result == AVERROR(EAGAIN)) |
| 582 | continue; |
| 583 | if (send_result < 0 && send_result != AVERROR_EOF) { |
| 584 | const std::string err = AvError(send_result); |
| 585 | av_frame_free(&decoded); |
| 586 | throw std::runtime_error("avcodec_send_packet failed: " + err); |
no test coverage detected