perf: prefer VideoToolbox decoding with software fallback
This commit is contained in:
+14
-4
@@ -2,6 +2,7 @@
|
||||
#include "player_macos.h"
|
||||
#include "output.hpp"
|
||||
#include "progress_reporter.hpp"
|
||||
#include "video_decoder.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
@@ -64,6 +65,7 @@ struct Track {
|
||||
AVPacket *packet = nullptr;
|
||||
bool packetPending = false;
|
||||
bool receiving = false;
|
||||
bool firstPacket = true;
|
||||
double packetBufferedEnd = 0;
|
||||
double decoderBufferedEnd = 0;
|
||||
bool sourceEnded = false;
|
||||
@@ -456,6 +458,7 @@ struct Player {
|
||||
track.codec->pkt_timebase = source->streams[index]->time_base;
|
||||
// A bounded software decoder pool; FFmpeg owns its internal frame reorder buffer.
|
||||
track.codec->thread_count = 2;
|
||||
if (type == AVMEDIA_TYPE_VIDEO) playback::preferVideoToolbox(track.codec);
|
||||
check(avcodec_open2(track.codec, decoder, nullptr), "Opening decoder");
|
||||
}
|
||||
|
||||
@@ -466,6 +469,7 @@ struct Player {
|
||||
if (!track.codec) continue;
|
||||
avcodec_flush_buffers(track.codec);
|
||||
track.drainSent = track.drained = false;
|
||||
track.firstPacket = true;
|
||||
av_packet_unref(track.packet);
|
||||
track.packetPending = track.receiving = track.sourceEnded = false;
|
||||
track.packetBufferedEnd = track.decoderBufferedEnd = 0;
|
||||
@@ -1086,8 +1090,11 @@ struct Player {
|
||||
return;
|
||||
skipPresentedTimestamp = AV_NOPTS_VALUE;
|
||||
}
|
||||
const int size = av_image_get_buffer_size(static_cast<AVPixelFormat>(decoded->format),
|
||||
decoded->width, decoded->height, 1);
|
||||
Frame frame(av_frame_alloc());
|
||||
if (!frame) throw std::bad_alloc();
|
||||
check(playback::refVideoFrame(frame.get(), decoded), "Mapping decoded video");
|
||||
const int size = av_image_get_buffer_size(static_cast<AVPixelFormat>(frame->format),
|
||||
frame->width, frame->height, 1);
|
||||
check(size, "Sizing decoded video");
|
||||
const auto bytes = static_cast<std::size_t>(size);
|
||||
if (bytes > videoByteLimit)
|
||||
@@ -1100,8 +1107,6 @@ struct Player {
|
||||
videoBytes -= video.back().bytes;
|
||||
video.pop_back();
|
||||
}
|
||||
Frame frame(av_frame_clone(decoded));
|
||||
if (!frame) throw std::bad_alloc();
|
||||
VideoFrame item{std::move(frame), pts, pts + frameDuration, bytes, track.timestampOccurrence};
|
||||
auto insertion = std::upper_bound(video.begin(), video.end(), pts,
|
||||
[](double value, const VideoFrame &entry) { return value < entry.pts; });
|
||||
@@ -1137,6 +1142,11 @@ struct Player {
|
||||
return true;
|
||||
}
|
||||
if (track.packetPending) {
|
||||
if (slot == 1 && track.firstPacket) {
|
||||
check(playback::prepareVideoPacket(track.codec, *track.stream()->codecpar, *track.packet),
|
||||
"Preparing video decoder preroll");
|
||||
track.firstPacket = false;
|
||||
}
|
||||
const int result = avcodec_send_packet(track.codec, track.packet);
|
||||
if (result != AVERROR(EAGAIN)) {
|
||||
check(result, "Sending media packet to decoder");
|
||||
|
||||
Reference in New Issue
Block a user